* [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages. @ 2022-02-08 15:13 Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (4 more replies) 0 siblings, 5 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:13 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath Racket 8.4 hasn't been released yet (expect it in a matter of days), but I wanted to solicit feedback on these changes early. On the Racket side of things, discussions upstream and with other distribution packagers have clarified what a ``minimal Racket'' package ought to consist of, which in turn suggested a nice new boundary between the lowest-level Racket VM packages, which are concerned with bootstrapping and platform support, and a more uniform use of layered and tethered installations for both the 'racket-minimal' and 'racket' packages. I've also started getting the sources for the other main-distribution Racket packages directly from their respective repositories, rather than extracting them from the bundled tarballs. All in all, it's a few steps closer to the goal of a build system for Racket packages. For Chez Scheme, I set out to package Racket's variant of Chez Scheme---which supports architectures not yet supported upstream, e.g. aarch64---and to share more between the upstream and Racket packages. I also tweaked various things I found along the way: hopefully some are clear improvements, though there are some prime opportunities for bikeshedding about naming things. Let me know what you think! -Philip Philip McGrath (9): gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: Add chez-scheme-racket-variant. gnu: racket: Update to 8.3.900. gnu/local.mk | 5 +- gnu/packages/chez-and-racket-bootstrap.scm | 1108 ++++++++++++ gnu/packages/chez.scm | 628 +++---- gnu/packages/emacs-xyz.scm | 4 +- gnu/packages/loko.scm | 4 +- .../racket-enable-scheme-backport.patch | 465 +++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1552 +++++++++++------ 8 files changed, 2850 insertions(+), 942 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 2/9] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (7 more replies) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 subsequent siblings) 4 siblings, 8 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. * gnu/packages/loko.scm: Likewise. * gnu/packages/racket.scm: Likewise. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 278 +++++++++++++++++++++ gnu/packages/chez.scm | 225 +---------------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- gnu/packages/racket.scm | 2 +- 6 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm diff --git a/gnu/local.mk b/gnu/local.mk index f14daf2edd..e3104fc0b6 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -144,6 +144,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/certs.scm \ %D%/packages/check.scm \ %D%/packages/chemistry.scm \ + %D%/packages/chez-and-racket-bootstrap.scm \ %D%/packages/chez.scm \ %D%/packages/chicken.scm \ %D%/packages/chromium.scm \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm new file mode 100644 index 0000000000..f102b099fb --- /dev/null +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch> +;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> +;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> +;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages chez-and-racket-bootstrap) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix utils) + #:use-module (guix gexp) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages compression) + #:use-module (gnu packages ghostscript) + #:use-module (gnu packages linux) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages netpbm) + #:use-module (gnu packages tex) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +;; Commentary: +;; +;; Alphabetically and chronologically, Chez comes before Racket. +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Putting the relevant definitions together in this module avoids having to +;; work around dependency cycles. +;; +;; Code: + +(define nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +(define stex + ;; This commit includes a fix, which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (version "1.2.2") + (version (git-version version "1" commit))) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name "stex" version))))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version "9.5.6") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet + ;; Remove bundled libraries. + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))))))) + (build-system gnu-build-system) + (inputs + `(("libuuid" ,util-linux "lib") + ("zlib" ,zlib) + ("zlib:static" ,zlib "static") + ("lz4" ,lz4) + ("lz4:static" ,lz4 "static") + ;; for expeditor: + ("ncurses" ,ncurses) + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + ("libx11" ,libx11))) + (native-inputs + `(("nanopass" ,nanopass) ; source only + ;; for docs + ("stex" ,stex) + ("xorg-rgb" ,xorg-rgb) + ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek))) + ("ghostscript" ,ghostscript) + ("netpbm" ,netpbm))) + (native-search-paths + (list (search-path-specification + (variable "CHEZSCHEMELIBDIRS") + (files (list (string-append "lib/csv" version "-site")))))) + (outputs '("out" "doc")) + (arguments + `(#:modules + ((guix build gnu-build-system) + (guix build utils) + (ice-9 ftw) + (ice-9 match)) + #:test-target "test" + #:configure-flags + '("--threads") ;; TODO when we fix armhf, it doesn't support --threads + #:phases + (modify-phases %standard-phases + ;; put these where configure expects them to be + (add-after 'unpack 'unpack-nanopass+stex + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (for-each (lambda (dep) + (define src + (assoc-ref (or native-inputs inputs) dep)) + (copy-recursively src dep + #:keep-mtime? #t)) + '("nanopass" "stex")))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs outputs + (configure-flags '()) + #:allow-other-keys) + (let* ((zlib-static (assoc-ref inputs "zlib:static")) + (lz4-static (assoc-ref inputs "lz4:static")) + (out (assoc-ref outputs "out")) + ;; add flags which are always required: + (flags (cons* + (string-append "--installprefix=" out) + (string-append "ZLIB=" zlib-static "/lib/libz.a") + (string-append "LZ4=" lz4-static "/lib/liblz4.a") + ;; Guix will do compress man pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" ,(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke + "./configure" + flags)))) + ;; The binary file name is called "scheme" as is the one from MIT/GNU + ;; Scheme. We add a symlink to use in case both are installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bin (string-append out "/bin")) + (lib (string-append out "/lib")) + (name "chez-scheme")) + (symlink (string-append bin "/scheme") + (string-append bin "/" name)) + (map (lambda (file) + (symlink file (string-append (dirname file) + "/" name ".boot"))) + (find-files lib "scheme.boot"))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (stex-output "/tmp") + (doc-dir (string-append stex-output + "/share/doc/" + stex+version))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/" + stex+version) + (string-append "Scheme=" + (assoc-ref outputs "out") + "/bin/scheme")) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((chez+version (strip-store-file-name + (assoc-ref outputs "out"))) + (stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + (scheme (string-append (assoc-ref outputs "out") + "/bin/scheme")) + ;; see note on stex-output in phase build-stex, above: + (stexlib (string-append "/tmp" + "/lib/" + stex+version)) + (doc-dir (string-append (assoc-ref outputs "doc") + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" + "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))) + ;; Chez Scheme does not have a MIPS backend. + ;; FIXME: Debian backports patches to get armhf working. + ;; We should too. It is the Chez machine type arm32le + ;; (no threaded version upstream yet, though there is in + ;; Racket's fork), more specifically (per the release notes) ARMv6. + (supported-systems (fold delete %supported-systems + '("mips64el-linux" "armhf-linux"))) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "R6RS Scheme compiler and run-time") + (description + "Chez Scheme is a compiler and run-time system for the language of the +Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler +generates native code for each target processor, with support for x86, x86_64, +and 32-bit PowerPC architectures.") + (license license:asl2.0))) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..caf61a95f5 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -4,7 +4,6 @@ ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,234 +31,12 @@ (define-module (gnu packages chez) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (guix build-system gnu) - #:use-module (gnu packages compression) - #:use-module (gnu packages ncurses) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages ghostscript) - #:use-module (gnu packages linux) - #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) - #:use-module (gnu packages compression) - #:use-module (gnu packages image) - #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - -(define-public chez-scheme - (package - (name "chez-scheme") - (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) - (build-system gnu-build-system) - (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) - (native-search-paths - (list (search-path-specification - (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) - (outputs '("out" "doc")) - (arguments - `(#:modules - ((guix build gnu-build-system) - (guix build utils) - (ice-9 ftw) - (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) - ;; Chez Scheme does not have a MIPS backend. - ;; FIXME: Debian backports patches to get armhf working. - ;; We should too. It is the Chez machine type arm32le - ;; (no threaded version upstream yet, though there is in - ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) - (home-page "https://cisco.github.io/ChezScheme/") - (synopsis "R6RS Scheme compiler and run-time") - (description - "Chez Scheme is a compiler and run-time system for the language of the -Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler -generates native code for each target processor, with support for x86, x86_64, -and 32-bit PowerPC architectures.") - (license asl2.0))) - (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 9b57b36623..c6a62e8767 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -145,7 +145,7 @@ (define-module (gnu packages emacs-xyz) #:use-module (gnu packages aspell) #:use-module (gnu packages audio) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages cmake) #:use-module (gnu packages code) #:use-module (gnu packages cpp) diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..74a649b8a1 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -24,7 +24,7 @@ (define-module (gnu packages loko) #:use-module (gnu packages package-management) #:use-module (gnu packages guile) #:use-module (gnu packages guile-xyz) - #:use-module (gnu packages chez)) + #:use-module (gnu packages chez-and-racket-bootstrap)) (define-public loko-scheme (package diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..865fdff70f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -34,7 +34,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages compression) #:use-module (gnu packages databases) #:use-module (gnu packages fontutils) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 2/9] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 3/9] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (6 subsequent siblings) 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". * gnu/packages/chez.scm (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez-and-racket-bootstrap.scm | 2 +- gnu/packages/chez.scm | 373 +++++++++++---------- 2 files changed, 191 insertions(+), 184 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f102b099fb..1ed4631ced 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -136,7 +136,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index caf61a95f5..54bbee7923 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -37,6 +37,28 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) + +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -54,13 +76,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -85,42 +105,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -144,95 +170,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -253,10 +258,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -284,10 +290,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -314,17 +321,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -354,10 +362,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -386,46 +395,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) (with-directory-excursion (dirname mk-file) (apply invoke "make" "build" make-flags))))) (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 3/9] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 2/9] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 4/9] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath ` (5 subsequent siblings) 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez-and-racket-bootstrap (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1ed4631ced..11d570059b 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -114,9 +114,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -169,14 +167,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 4/9] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 2/9] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 3/9] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 5/9] gnu: Add stex Philip McGrath ` (4 subsequent siblings) 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine->unthreaded, chez-machine->upstream-restriction, chez-machine->nix-system, nix-system->chez-machine): New private functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-machine->upstream-restriction'. --- gnu/packages/chez-and-racket-bootstrap.scm | 142 ++++++++++++++++++++- 1 file changed, 140 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 11d570059b..fc1da53178 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -28,7 +28,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (ice-9 match) + #:use-module (ice-9 regex) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -61,6 +63,134 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (chez-machine->unthreaded mach) + "Given a string MACH naming a Chez Scheme machine type, returns a string +naming the unthreaded machine type for the same architecture and OS as MACH. +The returned string may share storage with MACH." + (if (eqv? #\t (string-ref mach 0)) + (substring mach 1) + mach)) +(define (chez-machine->threaded mach) + "Like @code{chez-machine->unthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref mach 0)) + mach + (string-append "t" mach))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->upstream-restriction mach) + "Given a string MACH naming a Chez Scheme machine type, returns a symbol +naming a restriction on the upstream Chez Scheme implementation compared to +the Racket variant, or @code{#f} if no such restriction exists. The +restriction is reported for the architecture--OS pair, regardless of whether +MACH specifies a threaded or an unthreaded variant. + +Possible restrictions currently include: +@itemize @bullet +@item +@code{'no-threads}: Support for native threads is not available upstream. +@item +@code{'no-support}: The upstream release doesn't claim to support this +architecture--OS combination at all. +@end itemize + +See @code{chez-machine->nix-system} for more details about acceptable values +for MACH." + (let ((mach (chez-machine->unthreaded mach))) + (cond + ((string-prefix? "arm64" mach) + 'no-support) + ((string-prefix? "arm32" mach) + (if (string-suffix? "le" mach) + 'no-threads + 'no-support)) + ((string-prefix? "ppc32" mach) + (if (string-suffix? "le" mach) + #f + 'no-support)) + (else + #f)))) + +(define (chez-machine->nix-system mach) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACH. If MACH is not a string representing a known machine type, an exception +is raised. This function does not distinguish between threaded and unthreaded +variants of MACH. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by the Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((mach (chez-machine->unthreaded mach))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez mach) + (string-append + nix "-" (let ((mach-os (substring mach (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez mach-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional (system (%current-system)) + #:key (threads? 'always)) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +When THREADS? is @code{'always} (the default), the threaded variant of the +machine type will be returned: note that the package returned by +@code{chez-scheme-for-system} will always support native threads. When +THREADS? is @code{#f}, the unthreaded machine type will be returned. If +THREADS? is @code{'upstream} (the default), the threaded variant of the +machine type will be returned if and only if it is supported by upstream Chez +Scheme (see @code{chez-machine->upstream-restriction}). If THREADS? is any +other value, an exception is raised." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os)) + (mach (and chez-arch chez-os (string-append chez-arch chez-os)))) + (and mach + (match threads? + ('always + (chez-machine->threaded mach)) + (#f + mach) + ('upstream + (if (chez-machine->upstream-restriction mach) + mach + (chez-machine->threaded mach))))))) + +;; +;; Chez Scheme: +;; + (define nanopass (let ((version "1.9.2")) (origin @@ -264,8 +394,16 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter + (lambda (system) + (and=> (nix-system->chez-machine system) + (lambda (mach) + (not (eq? 'no-support + (chez-machine->upstream-restriction mach)))))) + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 5/9] gnu: Add stex. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (2 preceding siblings ...) 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 4/9] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 6/9] gnu: Add chez-nanopass Philip McGrath ` (3 subsequent siblings) 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New variable. (stex): Change from origin to package inheriting from 'stex-bootstrap'. (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove labels. Remove dependencies of stex-bootstrap. [inputs]: Remove labels. [arguments]: Adapt to use 'stex-bootstrap', 'search-input-file', and G-expressions. (nanopass): Make it public as a temporary workaround for Racket. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 435 ++++++++++++--------- gnu/packages/racket.scm | 5 +- 2 files changed, 263 insertions(+), 177 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index fc1da53178..c0d5e2897d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -31,6 +31,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -191,113 +192,83 @@ (define* (nix-system->chez-machine #:optional (system (%current-system)) ;; Chez Scheme: ;; -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define unbundle-chez-submodules + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) +(define (unpack-nanopass+stex) + ;; delayed resolution of `nanopass` + #~(begin + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet unbundle-chez-submodules))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) + (native-inputs (list stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + #$(unpack-nanopass+stex))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -305,90 +276,59 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'install-symlink 'install-doc + (lambda* (#:key native-inputs inputs outputs + #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib (search-input-directory + (or native-inputs inputs) + "/lib/stex")) + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" + doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le @@ -412,3 +352,150 @@ (define* (stex-make #:optional (suffix "")) generates native code for each target processor, with support for x86, x86_64, and 32-bit PowerPC architectures.") (license license:asl2.0))) + +;; +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") ;; can run without compiling + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + (let ((machine #$(nix-system->chez-machine + (or (%current-target-system) + (%current-system))))) + (if (and (not (eqv? #\t (string-ref machine 0))) + (string-contains scheme "racket")) + (string-append "t" machine) + machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine + "\\."))))) + (else + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is considered part of the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license license:expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 865fdff70f..d8338bcd6f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) + ("stex" ,(package-source stex)) + ("nanopass" ,nanopass))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 6/9] gnu: Add chez-nanopass. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (3 preceding siblings ...) 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 5/9] gnu: Add stex Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 7/9] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (2 subsequent siblings) 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-scheme)[native-inputs]: Add it. (chez-nanopass): New variable. (unpack-nanopass+stex): Adapt accordingly. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 96 ++++++++++++++++++---- gnu/packages/racket.scm | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index c0d5e2897d..9125d34ab7 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -203,12 +203,13 @@ (define unbundle-chez-submodules "lz4" "zlib")))) -(define (unpack-nanopass+stex) - ;; delayed resolution of `nanopass` +(define unpack-nanopass+stex #~(begin - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) (mkdir-p "stex") (with-output-to-file "stex/Mf-stex" (lambda () @@ -241,7 +242,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -261,7 +262,7 @@ (define-public chez-scheme #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args - #$(unpack-nanopass+stex))) + #$unpack-nanopass+stex)) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -490,12 +491,75 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license license:expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d8338bcd6f..e8d016c07b 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -334,7 +334,7 @@ (define-public racket-bootstrap-chez-bootfiles racket-minimal racket-minimal-bc-3m)) ("stex" ,(package-source stex)) - ("nanopass" ,nanopass))) + ("nanopass" ,(package-source chez-nanopass)))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 7/9] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (4 preceding siblings ...) 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 6/9] gnu: Add chez-nanopass Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 9/9] gnu: racket: Update to 8.3.900 Philip McGrath 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath This might seem a bit silly in isolation, but it makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]: Add new phase 'unpack-bootfiles'. [version, source, home-page]: Derive from 'chez-scheme-bootstrap-bootfiles'. --- gnu/packages/chez-and-racket-bootstrap.scm | 57 ++++++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 9125d34ab7..c6e4e07085 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -216,9 +216,9 @@ (define unpack-nanopass+stex ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) -(define-public chez-scheme +(define-public chez-scheme-bootstrap-bootfiles (package - (name "chez-scheme") + (name "chez-scheme-bootstrap-bootfiles") ;; The version should match `(scheme-version-number)`. ;; See s/cmacros.ss c. line 360. (version "9.5.6") @@ -230,8 +230,45 @@ (define-public chez-scheme (sha256 (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) + (file-name (git-file-name "chez-scheme" version)) (snippet unbundle-chez-submodules))) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((mach (nix-system->chez-machine system #:threads? #f))) + (or (equal? "arm32le" mach) + (and mach + (member (substring mach 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> mach) + '("le" "nt" "osx")))))) + %supported-systems)) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source.") + (properties `((hidden? . #t))) + (license license:asl2.0))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version (package-version chez-scheme-bootstrap-bootfiles)) + (source (package-source chez-scheme-bootstrap-bootfiles)) (build-system gnu-build-system) (inputs (list @@ -242,7 +279,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -263,6 +302,14 @@ (define-public chez-scheme (add-after 'unpack 'unpack-nanopass+stex (lambda args #$unpack-nanopass+stex)) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -345,7 +392,7 @@ (define* (stex-make #:optional (suffix "")) (not (eq? 'no-support (chez-machine->upstream-restriction mach)))))) %supported-systems))) - (home-page "https://cisco.github.io/ChezScheme/") + (home-page (package-home-page chez-scheme-bootstrap-bootfiles)) (synopsis "R6RS Scheme compiler and run-time") (description "Chez Scheme is a compiler and run-time system for the language of the -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (5 preceding siblings ...) 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 7/9] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 2022-02-09 13:42 ` Liliana Marie Prikler 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 9/9] gnu: racket: Update to 8.3.900 Philip McGrath 7 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. The new function 'chez-scheme-for-system' selects the Chez Scheme package that best supports the target system. In the process, we also add packages for 'racket-vm-cgc', 'racket-vm-bc', and 'racket-vm-cs'. A future commit will change 'racket-minimal' to use the Racket VM implementation that best supports the target system, as reported by 'racket-vm-for-system'. * gnu/packages/patches/racket-enable-scheme-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): (racket-vm-bc): (racket-vm-cs): (chez-scheme-racket-variant-bootstrap-bootfiles): (chez-scheme-racket-variant): New variables. (chez-scheme-for-system, racket-vm-for-system): New exported functions. * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise * gnu/packages/chez.scm (chez-srfi): (chez-web): (chez-sockets): (chez-matchable): (chez-irregex): (chez-fmt): (chez-mit): (chez-scmutils): Likewise. (chez-mit)[origin]<snippet>: Add workaround for Racket variant. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 512 +++++++++++++++++- gnu/packages/chez.scm | 40 +- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++ 6 files changed, 1003 insertions(+), 19 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index e3104fc0b6..94de782ca9 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1785,6 +1785,7 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index c6e4e07085..46da8e3ef2 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -34,15 +34,20 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) + #:use-module (gnu packages autotools) + #:use-module (gnu packages bash) #:use-module (gnu packages compression) #:use-module (gnu packages ghostscript) + #:use-module (gnu packages libffi) #:use-module (gnu packages linux) #:use-module (gnu packages ncurses) #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) #:use-module (gnu packages xorg) #:use-module ((guix licenses) - #:prefix license:)) + #:prefix license:) + #:export (chez-scheme-for-system + racket-vm-for-system)) ;; Commentary: ;; @@ -62,8 +67,164 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; Putting the relevant definitions together in this module avoids having to ;; work around dependency cycles. ;; +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) One way of thinking about the +;; bounary between the Racket VM and Racket programs is that the VM implements +;; the primitives accessed by the 'ffi/unsafe/vm' library. Another perspective +;; is that DrRacket's ``Open defining file''/``Jump to definition'' features +;; can navigate into Racket programs, including into the implementation of +;; 'racket/base', but can not jump into the implementation of the Racket VM +;; itself. A third, related perspective is that Racket code is usually +;; installed with source files alongside compiled code (though this is not +;; mandatory), whereas the Racket VM is installed only in compiled form. +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. The use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: +;; +;; - Racket BC [CGC] can be built with only a C compiler (except for +;; one caveat discussed below). +;; - Racket BC [3M] needs an existing Racket to run "xform", +;; which transforms its own C source code to add additional annotations +;; for the precise garbage collector. +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. +;; It also needs an existing Racket to compile Racket-implemented +;; parts of the runtime system to R6RS libraries. +;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate +;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler +;; purely from source into Racket and apply the compiler to itself, +;; producing the needed bootfiles (albeit very slowly). +;; Any variant of Racket since version 7.1 can run the simulation. +;; +;; So, we build CGC to build 3M to build bootfiles and CS. +;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; +;; One remaining bootstrapping limitation is that Racket's reader, module +;; system, and macro expander are implemented in Racket. For Racket CS, +;; they are compiled to R6RS libraries as discussed above. This note from the +;; README file applies to all such subsystems: +;; +;; The Racket version must be practically the same as the current Racket +;; verson, although it can be the Racket BC implementation (instead of +;; the Racket CS implementation). +;; +;; Unlike Chez Scheme boot files, the files generated in "schemified" +;; are human-readable and -editable Scheme code. That provides a way +;; out of bootstrapping black holes, even without BC. +;; +;; However, other Racket subsystems implemented in Racket for Racket CS +;; use older C implementations for Racket BC, whereas the reader, expander, +;; and module system were completely replaced with the Racket implementation +;; +;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) +;; are embeded in C as a static string constant. Eventually, they are further +;; compiled by the C-implemented Racket BC bytecode and JIT compilers. +;; (On platforms where Racket BC's JIT is not supported, yet another compiler +;; instead compiles the linklets to C code, but this is not a bootstrapping +;; issue.) +;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' if it supports SYSTEM without restrictions; +'chez-scheme-racket-variant' otherwise." + (if (and=> (nix-system->chez-machine system) + chez-machine->upstream-restriction) + chez-scheme-racket-variant + chez-scheme)) + +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->unthreaded mach) "Given a string MACH naming a Chez Scheme machine type, returns a string naming the unthreaded machine type for the same architecture and OS as MACH. @@ -189,19 +350,19 @@ (define* (nix-system->chez-machine #:optional (system (%current-system)) (chez-machine->threaded mach))))))) ;; -;; Chez Scheme: +;; Chez auxiliary G-expressions: ;; (define unbundle-chez-submodules #~(begin (use-modules (guix build utils)) (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib")))) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) (define unpack-nanopass+stex #~(begin @@ -216,6 +377,235 @@ (define unpack-nanopass+stex ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) +;; +;; Racket VM: +;; + +(define (racket-vm-common-configure-flags) + ;; under a lambda extraction to avoid evaluating bash-minimal too early + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip" + "--enable-origtree")) + +(define-public racket-vm-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-vm-cgc") + (version "8.3.900") + ;; ^ Remember to also update the version of + ;; chez-scheme-racket-variant-bootstrap-bootfiles + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + ;;(commit (string-append "v" version)))) + (commit "a8f2969753f70e70d73308250cae1d4eda087319"))) + (sha256 + (base32 "141c18wmvb6039cw87mvmm6xxs6k01wkcrxj0hfa1r8za25qa934")) + (file-name (git-file-name "racket" version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + #$unbundle-chez-submodules) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants + (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") + #:phases + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + +(define-public racket-vm-bc + (package + (inherit racket-vm-cgc) + (name "racket-vm-bc") + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket BC [3M] implementation") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) + +(define-public racket-vm-cs + (package + (inherit racket-vm-bc) + (name "racket-vm-cs") + (inputs + (modify-inputs (package-inputs racket-vm-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (delete "libtool") + (prepend chez-scheme-racket-variant + chez-nanopass-bootstrap + racket-vm-bc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$unpack-nanopass+stex))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-racket-variant") + "/bin/scheme") + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. + +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + +;; +;; Chez Scheme: +;; + (define-public chez-scheme-bootstrap-bootfiles (package (name "chez-scheme-bootstrap-bootfiles") @@ -401,6 +791,112 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license license:asl2.0))) + +(define-public chez-scheme-racket-variant-bootstrap-bootfiles + (package + (inherit chez-scheme-bootstrap-bootfiles) + (name "chez-scheme-racket-variant-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + (source (package-source racket-vm-cgc)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) + (arguments + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme.") + (properties `()) + (license license:asl2.0))) + +(define-public chez-scheme-racket-variant + (package + (inherit chez-scheme) + (name "chez-scheme-racket-variant") + (version (package-version chez-scheme-racket-variant-bootstrap-bootfiles)) + (source (package-source racket-vm-cgc)) + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-racket-variant-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page + (package-home-page chez-scheme-racket-variant-bootstrap-bootfiles)) + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license license:asl2.0))) + ;; ;; Chez's bootstrap dependencies: ;; diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 54bbee7923..aa8c305d72 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -74,7 +74,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -105,7 +105,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -170,7 +170,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -256,7 +256,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -288,7 +288,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -319,7 +319,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -355,12 +355,34 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-racket-variant. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -391,7 +413,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index c6a62e8767..54774d9cad 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index 74a649b8a1..a7ab12a0c4 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant Philip McGrath @ 2022-02-09 13:42 ` Liliana Marie Prikler 2022-02-10 1:30 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-09 13:42 UTC (permalink / raw) To: Philip McGrath, 53878 Am Dienstag, dem 08.02.2022 um 10:18 -0500 schrieb Philip McGrath: > The Racket variant of Chez Scheme can be used to support platforms > that > are not yet supported by upstream Chez Scheme. The new function > 'chez-scheme-for-system' selects the Chez Scheme package that best > supports the target system. > > In the process, we also add packages for 'racket-vm-cgc', > 'racket-vm-bc', and 'racket-vm-cs'. A future commit will change > 'racket-minimal' to use the Racket VM implementation that best > supports > the target system, as reported by 'racket-vm-for-system'. > > * gnu/packages/patches/racket-enable-scheme-backport.patch: New > patch. > * gnu/local.mk (dist_patch_DATA): Add it. > * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): > (racket-vm-bc): > (racket-vm-cs): > (chez-scheme-racket-variant-bootstrap-bootfiles): > (chez-scheme-racket-variant): New variables. > (chez-scheme-for-system, racket-vm-for-system): New exported > functions. > * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. > * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise > * gnu/packages/chez.scm (chez-srfi): > (chez-web): > (chez-sockets): > (chez-matchable): > (chez-irregex): > (chez-fmt): > (chez-mit): > (chez-scmutils): Likewise. > (chez-mit)[origin]<snippet>: Add workaround for Racket variant. This patch does a lot and should probably be separated into several commits. As far as the name "chez-scheme-racket-variant" is concerned, I am not really a fan of it. How would "chez-scheme-for-racket" sound? ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant. 2022-02-09 13:42 ` Liliana Marie Prikler @ 2022-02-10 1:30 ` Philip McGrath 2022-02-10 7:08 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-10 1:30 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/9/22 08:42, Liliana Marie Prikler wrote: > Am Dienstag, dem 08.02.2022 um 10:18 -0500 schrieb Philip McGrath: > This patch does a lot and should probably be separated into several > commits. As far as the name "chez-scheme-racket-variant" is concerned, > I am not really a fan of it. How would "chez-scheme-for-racket" sound? > Thanks for taking a look! Calling it "chez-scheme-for-racket" is fine with me---it's a little shorter, at least. As far as splitting it up, yes, that makes sense. (There had at one point been some entanglements that I thought would make that difficult, but I've since fixed all those issues anyway.) What do you think of splitting it like this? >> * gnu/packages/patches/racket-enable-scheme-backport.patch: New >> patch. >> * gnu/local.mk (dist_patch_DATA): Add it. >> * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): --- >> (racket-vm-bc): --- >> (racket-vm-cs): --- >> (chez-scheme-racket-variant-bootstrap-bootfiles): >> (chez-scheme-racket-variant): New variables. --- >> (chez-scheme-for-system, --- >> (chez-mit)[origin]<snippet>: Add workaround for Racket variant. --- >> * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. >> * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise >> * gnu/packages/chez.scm (chez-srfi): >> (chez-web): >> (chez-sockets): >> (chez-matchable): >> (chez-irregex): >> (chez-fmt): >> (chez-mit): >> (chez-scmutils): Likewise. --- >> racket-vm-for-system): New exported >> functions. Alternatively, I could see adding the snippet to "chez-mit" in the same commit as changing it to use "chez-scheme-for-system", or I could split each changed package into its own commit (though those would be extremely small), or put the definition of "chez-scheme-for-system" together with its uses, or ... Racket 8.4 was just released,[0] so I plan to send a revised series today or tomorrow. -Philip [0]: https://blog.racket-lang.org/2022/02/racket-v8-4.html ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant. 2022-02-10 1:30 ` Philip McGrath @ 2022-02-10 7:08 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-10 7:08 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Mittwoch, dem 09.02.2022 um 20:30 -0500 schrieb Philip McGrath: > Calling it "chez-scheme-for-racket" is fine with me---it's a little > shorter, at least. Okay. > As far as splitting it up, yes, that makes sense. (There had at one > point been some entanglements that I thought would make that > difficult, but I've since fixed all those issues anyway.) What do you > think of splitting it like this? I'm not entirely sure how the interdependencies are, but I'd do... > >> * gnu/packages/patches/racket-enable-scheme-backport.patch: New > >> patch. > >> * gnu/local.mk (dist_patch_DATA): Add it. > >> * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): > --- > >> (racket-vm-bc): > --- > >> (racket-vm-cs): > --- > >> (chez-scheme-for-racket-bootstrap-bootfiles): > >> (chez-scheme-for-racket): New variables. These, then > >> (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for- > racket. then > --- > >> (chez-scheme-for-system, racket-vm-for-system): New variables. > --- > >> * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for- > system'. > >> * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise > >> * gnu/packages/chez.scm (chez-srfi): > >> (chez-web): > >> (chez-sockets): > >> (chez-matchable): > >> (chez-irregex): > >> (chez-fmt): > >> (chez-mit): > >> (chez-scmutils): Likewise. > --- If that's not possible, you can keep racket-vm-for-system as the final patch. > Racket 8.4 was just released,[0] so I plan to send a revised series > today or tomorrow. Cool. > [0]: https://blog.racket-lang.org/2022/02/racket-v8-4.html ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-10 7:08 ` Liliana Marie Prikler @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 01/11] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (10 more replies) 0 siblings, 11 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath Hi, Here's a revised series with the actual Racket 8.4 release! I've split the 'chez-scheme-for-racket' patch basically as Liliana suggested in <https://issues.guix.gnu.org/53878#12> except that I've added 'racket-vm-for-system' in the commit which actually uses it (the final one), rather than the commit that adds 'chez-scheme-for-system'. -Philip Philip McGrath (11): gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: Add chez-scheme-for-racket. gnu: chez-mit: Support chez-scheme-for-racket. gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. gnu: racket: Update to 8.4. gnu/local.mk | 6 +- gnu/packages/chez-and-racket-bootstrap.scm | 1103 + gnu/packages/chez.scm | 628 +- gnu/packages/emacs-xyz.scm | 4 +- gnu/packages/loko.scm | 4 +- .../racket-enable-scheme-backport.patch | 465 + ...acket-gui-tethered-launcher-backport.patch | 26 + .../patches/racket-srfi-fsdg-backport.patch | 41622 ++++++++++++++++ gnu/packages/racket.scm | 1554 +- 9 files changed, 44470 insertions(+), 942 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch create mode 100644 gnu/packages/patches/racket-srfi-fsdg-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 01/11] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 02/11] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (9 subsequent siblings) 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. * gnu/packages/loko.scm: Likewise. * gnu/packages/racket.scm: Likewise. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 278 +++++++++++++++++++++ gnu/packages/chez.scm | 225 +---------------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- gnu/packages/racket.scm | 2 +- 6 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm diff --git a/gnu/local.mk b/gnu/local.mk index 1b08b40b9c..72e086d465 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -144,6 +144,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/certs.scm \ %D%/packages/check.scm \ %D%/packages/chemistry.scm \ + %D%/packages/chez-and-racket-bootstrap.scm \ %D%/packages/chez.scm \ %D%/packages/chicken.scm \ %D%/packages/chromium.scm \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm new file mode 100644 index 0000000000..f102b099fb --- /dev/null +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch> +;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> +;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> +;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages chez-and-racket-bootstrap) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix utils) + #:use-module (guix gexp) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages compression) + #:use-module (gnu packages ghostscript) + #:use-module (gnu packages linux) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages netpbm) + #:use-module (gnu packages tex) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +;; Commentary: +;; +;; Alphabetically and chronologically, Chez comes before Racket. +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Putting the relevant definitions together in this module avoids having to +;; work around dependency cycles. +;; +;; Code: + +(define nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +(define stex + ;; This commit includes a fix, which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (version "1.2.2") + (version (git-version version "1" commit))) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name "stex" version))))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version "9.5.6") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet + ;; Remove bundled libraries. + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))))))) + (build-system gnu-build-system) + (inputs + `(("libuuid" ,util-linux "lib") + ("zlib" ,zlib) + ("zlib:static" ,zlib "static") + ("lz4" ,lz4) + ("lz4:static" ,lz4 "static") + ;; for expeditor: + ("ncurses" ,ncurses) + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + ("libx11" ,libx11))) + (native-inputs + `(("nanopass" ,nanopass) ; source only + ;; for docs + ("stex" ,stex) + ("xorg-rgb" ,xorg-rgb) + ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek))) + ("ghostscript" ,ghostscript) + ("netpbm" ,netpbm))) + (native-search-paths + (list (search-path-specification + (variable "CHEZSCHEMELIBDIRS") + (files (list (string-append "lib/csv" version "-site")))))) + (outputs '("out" "doc")) + (arguments + `(#:modules + ((guix build gnu-build-system) + (guix build utils) + (ice-9 ftw) + (ice-9 match)) + #:test-target "test" + #:configure-flags + '("--threads") ;; TODO when we fix armhf, it doesn't support --threads + #:phases + (modify-phases %standard-phases + ;; put these where configure expects them to be + (add-after 'unpack 'unpack-nanopass+stex + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (for-each (lambda (dep) + (define src + (assoc-ref (or native-inputs inputs) dep)) + (copy-recursively src dep + #:keep-mtime? #t)) + '("nanopass" "stex")))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs outputs + (configure-flags '()) + #:allow-other-keys) + (let* ((zlib-static (assoc-ref inputs "zlib:static")) + (lz4-static (assoc-ref inputs "lz4:static")) + (out (assoc-ref outputs "out")) + ;; add flags which are always required: + (flags (cons* + (string-append "--installprefix=" out) + (string-append "ZLIB=" zlib-static "/lib/libz.a") + (string-append "LZ4=" lz4-static "/lib/liblz4.a") + ;; Guix will do compress man pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" ,(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke + "./configure" + flags)))) + ;; The binary file name is called "scheme" as is the one from MIT/GNU + ;; Scheme. We add a symlink to use in case both are installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bin (string-append out "/bin")) + (lib (string-append out "/lib")) + (name "chez-scheme")) + (symlink (string-append bin "/scheme") + (string-append bin "/" name)) + (map (lambda (file) + (symlink file (string-append (dirname file) + "/" name ".boot"))) + (find-files lib "scheme.boot"))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (stex-output "/tmp") + (doc-dir (string-append stex-output + "/share/doc/" + stex+version))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/" + stex+version) + (string-append "Scheme=" + (assoc-ref outputs "out") + "/bin/scheme")) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((chez+version (strip-store-file-name + (assoc-ref outputs "out"))) + (stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + (scheme (string-append (assoc-ref outputs "out") + "/bin/scheme")) + ;; see note on stex-output in phase build-stex, above: + (stexlib (string-append "/tmp" + "/lib/" + stex+version)) + (doc-dir (string-append (assoc-ref outputs "doc") + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" + "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))) + ;; Chez Scheme does not have a MIPS backend. + ;; FIXME: Debian backports patches to get armhf working. + ;; We should too. It is the Chez machine type arm32le + ;; (no threaded version upstream yet, though there is in + ;; Racket's fork), more specifically (per the release notes) ARMv6. + (supported-systems (fold delete %supported-systems + '("mips64el-linux" "armhf-linux"))) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "R6RS Scheme compiler and run-time") + (description + "Chez Scheme is a compiler and run-time system for the language of the +Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler +generates native code for each target processor, with support for x86, x86_64, +and 32-bit PowerPC architectures.") + (license license:asl2.0))) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..caf61a95f5 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -4,7 +4,6 @@ ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,234 +31,12 @@ (define-module (gnu packages chez) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (guix build-system gnu) - #:use-module (gnu packages compression) - #:use-module (gnu packages ncurses) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages ghostscript) - #:use-module (gnu packages linux) - #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) - #:use-module (gnu packages compression) - #:use-module (gnu packages image) - #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - -(define-public chez-scheme - (package - (name "chez-scheme") - (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) - (build-system gnu-build-system) - (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) - (native-search-paths - (list (search-path-specification - (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) - (outputs '("out" "doc")) - (arguments - `(#:modules - ((guix build gnu-build-system) - (guix build utils) - (ice-9 ftw) - (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) - ;; Chez Scheme does not have a MIPS backend. - ;; FIXME: Debian backports patches to get armhf working. - ;; We should too. It is the Chez machine type arm32le - ;; (no threaded version upstream yet, though there is in - ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) - (home-page "https://cisco.github.io/ChezScheme/") - (synopsis "R6RS Scheme compiler and run-time") - (description - "Chez Scheme is a compiler and run-time system for the language of the -Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler -generates native code for each target processor, with support for x86, x86_64, -and 32-bit PowerPC architectures.") - (license asl2.0))) - (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index e4390bad96..02694b636a 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -145,7 +145,7 @@ (define-module (gnu packages emacs-xyz) #:use-module (gnu packages aspell) #:use-module (gnu packages audio) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages cmake) #:use-module (gnu packages code) #:use-module (gnu packages cpp) diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..74a649b8a1 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -24,7 +24,7 @@ (define-module (gnu packages loko) #:use-module (gnu packages package-management) #:use-module (gnu packages guile) #:use-module (gnu packages guile-xyz) - #:use-module (gnu packages chez)) + #:use-module (gnu packages chez-and-racket-bootstrap)) (define-public loko-scheme (package diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..865fdff70f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -34,7 +34,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages compression) #:use-module (gnu packages databases) #:use-module (gnu packages fontutils) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 02/11] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 01/11] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 03/11] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (8 subsequent siblings) 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". * gnu/packages/chez.scm (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez-and-racket-bootstrap.scm | 2 +- gnu/packages/chez.scm | 373 +++++++++++---------- 2 files changed, 191 insertions(+), 184 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f102b099fb..1ed4631ced 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -136,7 +136,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index caf61a95f5..54bbee7923 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -37,6 +37,28 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) + +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -54,13 +76,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -85,42 +105,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -144,95 +170,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -253,10 +258,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -284,10 +290,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -314,17 +321,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -354,10 +362,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -386,46 +395,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) (with-directory-excursion (dirname mk-file) (apply invoke "make" "build" make-flags))))) (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 03/11] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 01/11] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 02/11] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath ` (7 subsequent siblings) 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez-and-racket-bootstrap (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1ed4631ced..11d570059b 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -114,9 +114,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -169,14 +167,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 03/11] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-14 14:34 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 05/11] gnu: Add stex Philip McGrath ` (6 subsequent siblings) 10 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine->unthreaded, chez-machine->upstream-restriction, chez-machine->nix-system, nix-system->chez-machine): New private functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-machine->upstream-restriction'. --- gnu/packages/chez-and-racket-bootstrap.scm | 142 ++++++++++++++++++++- 1 file changed, 140 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 11d570059b..fc1da53178 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -28,7 +28,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (ice-9 match) + #:use-module (ice-9 regex) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -61,6 +63,134 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (chez-machine->unthreaded mach) + "Given a string MACH naming a Chez Scheme machine type, returns a string +naming the unthreaded machine type for the same architecture and OS as MACH. +The returned string may share storage with MACH." + (if (eqv? #\t (string-ref mach 0)) + (substring mach 1) + mach)) +(define (chez-machine->threaded mach) + "Like @code{chez-machine->unthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref mach 0)) + mach + (string-append "t" mach))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->upstream-restriction mach) + "Given a string MACH naming a Chez Scheme machine type, returns a symbol +naming a restriction on the upstream Chez Scheme implementation compared to +the Racket variant, or @code{#f} if no such restriction exists. The +restriction is reported for the architecture--OS pair, regardless of whether +MACH specifies a threaded or an unthreaded variant. + +Possible restrictions currently include: +@itemize @bullet +@item +@code{'no-threads}: Support for native threads is not available upstream. +@item +@code{'no-support}: The upstream release doesn't claim to support this +architecture--OS combination at all. +@end itemize + +See @code{chez-machine->nix-system} for more details about acceptable values +for MACH." + (let ((mach (chez-machine->unthreaded mach))) + (cond + ((string-prefix? "arm64" mach) + 'no-support) + ((string-prefix? "arm32" mach) + (if (string-suffix? "le" mach) + 'no-threads + 'no-support)) + ((string-prefix? "ppc32" mach) + (if (string-suffix? "le" mach) + #f + 'no-support)) + (else + #f)))) + +(define (chez-machine->nix-system mach) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACH. If MACH is not a string representing a known machine type, an exception +is raised. This function does not distinguish between threaded and unthreaded +variants of MACH. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by the Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((mach (chez-machine->unthreaded mach))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez mach) + (string-append + nix "-" (let ((mach-os (substring mach (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez mach-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional (system (%current-system)) + #:key (threads? 'always)) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +When THREADS? is @code{'always} (the default), the threaded variant of the +machine type will be returned: note that the package returned by +@code{chez-scheme-for-system} will always support native threads. When +THREADS? is @code{#f}, the unthreaded machine type will be returned. If +THREADS? is @code{'upstream} (the default), the threaded variant of the +machine type will be returned if and only if it is supported by upstream Chez +Scheme (see @code{chez-machine->upstream-restriction}). If THREADS? is any +other value, an exception is raised." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os)) + (mach (and chez-arch chez-os (string-append chez-arch chez-os)))) + (and mach + (match threads? + ('always + (chez-machine->threaded mach)) + (#f + mach) + ('upstream + (if (chez-machine->upstream-restriction mach) + mach + (chez-machine->threaded mach))))))) + +;; +;; Chez Scheme: +;; + (define nanopass (let ((version "1.9.2")) (origin @@ -264,8 +394,16 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter + (lambda (system) + (and=> (nix-system->chez-machine system) + (lambda (mach) + (not (eq? 'no-support + (chez-machine->upstream-restriction mach)))))) + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-13 21:51 ` [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-14 14:34 ` Liliana Marie Prikler 2022-02-16 22:54 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-14 14:34 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > [...] > +(define (chez-machine->upstream-restriction mach) > + "Given a string MACH naming a Chez Scheme machine type, returns a > symbol > +naming a restriction on the upstream Chez Scheme implementation > compared to > +the Racket variant, or @code{#f} if no such restriction exists. The > +restriction is reported for the architecture--OS pair, regardless of > whether > +MACH specifies a threaded or an unthreaded variant. > + > +Possible restrictions currently include: > +@itemize @bullet > +@item > +@code{'no-threads}: Support for native threads is not available > upstream. > +@item > +@code{'no-support}: The upstream release doesn't claim to support > this > +architecture--OS combination at all. > +@end itemize > + > +See @code{chez-machine->nix-system} for more details about > acceptable values > +for MACH." > + (let ((mach (chez-machine->unthreaded mach))) > + (cond > + ((string-prefix? "arm64" mach) > + 'no-support) > + ((string-prefix? "arm32" mach) > + (if (string-suffix? "le" mach) > + 'no-threads > + 'no-support)) > + ((string-prefix? "ppc32" mach) > + (if (string-suffix? "le" mach) > + #f > + 'no-support)) > + (else > + #f)))) -> is a conversion operator, not an "accessor". "upstream-restriction" sounds rather negative, I'd rather have (chez- machine-features), which yields #f if the machine is unsupported and a (possibly empty) list of features otherwise, such as '(threads). I'm also not quite sure what the point is behind using chez machines here. Why not simply test the systems with the predicates we already have, i.e. target-arm64?, target-arm32?, target-linux?, target-ppc32?, ... And as a minor pet peeve, you ought to spell out machine. > +(define* (nix-system->chez-machine #:optional (system (%current- > system)) > + #:key (threads? 'always)) > + "Return the Chez Scheme machine type corresponding to the Nix > system > +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a > Chez Scheme > +machine type is undefined. > + > +When THREADS? is @code{'always} (the default), the threaded variant > of the > +machine type will be returned: note that the package returned by > +@code{chez-scheme-for-system} will always support native threads. > When > +THREADS? is @code{#f}, the unthreaded machine type will be > returned. If > +THREADS? is @code{'upstream} (the default), the threaded variant of > the > +machine type will be returned if and only if it is supported by > upstream Chez > +Scheme (see @code{chez-machine->upstream-restriction}). If THREADS? > is any > +other value, an exception is raised." What's the point in having THREADS? 'always? In any case, assuming chez-machine-features is to be exported, this can easily be checked -- even if not, we can add the check internally by writing #:key (threads? (chez-supports-threads? system)) > + (let* ((hyphen (string-index system #\-)) > + (nix-arch (substring system 0 hyphen)) > + (nix-os (substring system (+ 1 hyphen))) > + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) > + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os)) > + (mach (and chez-arch chez-os (string-append chez-arch chez- > os)))) This series of let-bindings should probably be done in a separate function called nix-system->chez-machine. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-14 14:34 ` Liliana Marie Prikler @ 2022-02-16 22:54 ` Philip McGrath 2022-02-17 7:24 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-16 22:54 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/14/22 09:34, Liliana Marie Prikler wrote: > Hi, > > Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >> [...] >> +(define (chez-machine->upstream-restriction mach) >> + "Given a string MACH naming a Chez Scheme machine type, returns a >> symbol >> +naming a restriction on the upstream Chez Scheme implementation >> compared to >> +the Racket variant, or @code{#f} if no such restriction exists. The >> +restriction is reported for the architecture--OS pair, regardless of >> whether >> +MACH specifies a threaded or an unthreaded variant. >> + >> +Possible restrictions currently include: >> +@itemize @bullet >> +@item >> +@code{'no-threads}: Support for native threads is not available >> upstream. >> +@item >> +@code{'no-support}: The upstream release doesn't claim to support >> this >> +architecture--OS combination at all. >> +@end itemize >> + >> +See @code{chez-machine->nix-system} for more details about >> acceptable values >> +for MACH." >> + (let ((mach (chez-machine->unthreaded mach))) >> + (cond >> + ((string-prefix? "arm64" mach) >> + 'no-support) >> + ((string-prefix? "arm32" mach) >> + (if (string-suffix? "le" mach) >> + 'no-threads >> + 'no-support)) >> + ((string-prefix? "ppc32" mach) >> + (if (string-suffix? "le" mach) >> + #f >> + 'no-support)) >> + (else >> + #f)))) > -> is a conversion operator, not an "accessor". I thought of this as a conversion more than an accessor. > "upstream-restriction" sounds rather negative, I'd rather have (chez- > machine-features), which yields #f if the machine is unsupported and a > (possibly empty) list of features otherwise, such as '(threads). > > I'm also not quite sure what the point is behind using chez machines > here. Why not simply test the systems with the predicates we already > have, i.e. target-arm64?, target-arm32?, target-linux?, target-ppc32?, > ... I agree that the name of this procedure should avoid sounding negative: 'restriction' was the best I'd come up with so far. I think I like 'chez-machine-features' somewhat better, but with a few reservations. Using predicates like 'target-arm32?' makes some sense overall, and I'll try it. One subtly is that systems supported by neither upstream nor Racket are currently handled by `and=>` in clients. Also, I guess it's odd to have this function operate on Chez Scheme machine types anyway, since a machine type specifies threaded or unthreaded. I'm currently thinking something like: --8<---------------cut here---------------start------------->8--- (define* (chez-upstream-features-for-system #:optional (system (or (%current-target-system) (%current-system)))) (cond ((not (nix-system->chez-machine system)) #f) ((target-arm64? system) #f) ((target-arm32? system) (and (target-linux? system) '())) ((target-ppc32? system) (and (target-linux? system) '(threads))) (else '(threads)))) --8<---------------cut here---------------end--------------->8--- Alternatively, there could be an argument called something like "variant", where the default would be 'upstream or maybe #f, and supplying 'racket would always return '(threads). (Racket CS requires the threaded version of Chez Scheme, so the chez-scheme-for-racket has consistently added thread support immediately upon adding any new target.) > > And as a minor pet peeve, you ought to spell out machine. > Ok, will do. > >> +(define* (nix-system->chez-machine #:optional (system (%current- >> system)) This should have been (or (%current-target-system) (%current-system)). >> + #:key (threads? 'always)) >> + "Return the Chez Scheme machine type corresponding to the Nix >> system >> +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a >> Chez Scheme >> +machine type is undefined. >> + >> +When THREADS? is @code{'always} (the default), the threaded variant >> of the >> +machine type will be returned: note that the package returned by >> +@code{chez-scheme-for-system} will always support native threads. >> When >> +THREADS? is @code{#f}, the unthreaded machine type will be >> returned. If >> +THREADS? is @code{'upstream} (the default), the threaded variant of >> the >> +machine type will be returned if and only if it is supported by >> upstream Chez >> +Scheme (see @code{chez-machine->upstream-restriction}). If THREADS? >> is any >> +other value, an exception is raised." > What's the point in having THREADS? 'always? In any case, assuming > chez-machine-features is to be exported, this can easily be checked -- > even if not, we can add the check internally by writing > #:key (threads? (chez-supports-threads? system)) > >> + (let* ((hyphen (string-index system #\-)) >> + (nix-arch (substring system 0 hyphen)) >> + (nix-os (substring system (+ 1 hyphen))) >> + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) >> + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os)) >> + (mach (and chez-arch chez-os (string-append chez-arch chez- >> os)))) > This series of let-bindings should probably be done in a separate > function called nix-system->chez-machine. On the one hand, the result of 'chez-scheme-for-system' will always support threads, so being threaded by default is convenient. On the other hand, it looks like I've reduced the use of this function (by searching for files rather than coding in the machine type directory) enough that it doesn't have a big impact either way. It will be more important when we support cross-compilation, and I think we should keep these functions internal and defer as much as possible of their API design until then. For now, I think I'll say that it's unspecified whether the result is a threaded or unthreaded machine type and add `chez-machine->{un,}threaded` as needed. -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-16 22:54 ` Philip McGrath @ 2022-02-17 7:24 ` Liliana Marie Prikler 2022-02-17 7:37 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-17 7:24 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Mittwoch, dem 16.02.2022 um 17:54 -0500 schrieb Philip McGrath: > > > +See @code{chez-machine->nix-system} for more details about > > > acceptable values > > > +for MACH." > > > + (let ((mach (chez-machine->unthreaded mach))) > > > + (cond > > > + ((string-prefix? "arm64" mach) > > > + 'no-support) > > > + ((string-prefix? "arm32" mach) > > > + (if (string-suffix? "le" mach) > > > + 'no-threads > > > + 'no-support)) > > > + ((string-prefix? "ppc32" mach) > > > + (if (string-suffix? "le" mach) > > > + #f > > > + 'no-support)) > > > + (else > > > + #f)))) > > -> is a conversion operator, not an "accessor". > > I thought of this as a conversion more than an accessor. Conversion follows the lines of "is (roughly) a", whereas this is a "has a" relation, which would imply accessing things. > > "upstream-restriction" sounds rather negative, I'd rather have > > (chez-machine-features), which yields #f if the machine is > > unsupported and a (possibly empty) list of features otherwise, such > > as '(threads). > > > > I'm also not quite sure what the point is behind using chez > > machines here. Why not simply test the systems with the predicates > > we already have, i.e. target-arm64?, target-arm32?, target-linux?, > > target-ppc32?, > > ... > > I agree that the name of this procedure should avoid sounding > negative: 'restriction' was the best I'd come up with so far. I > think I like 'chez-machine-features' somewhat better, but with a few > reservations. > > Using predicates like 'target-arm32?' makes some sense overall, and > I'll try it. One subtly (sic) is that systems supported by neither > upstream nor Racket are currently handled by `and=>` in clients. > > Also, I guess it's odd to have this function operate on Chez Scheme > machine types anyway, since a machine type specifies threaded or > unthreaded. Not sure how to deal with these reservations or what they'd imply, so following along. > I'm currently thinking something like: > > --8<---------------cut here---------------start------------->8--- > (define* (chez-upstream-features-for-system #:optional > (system (or > (%current-target-system) > > (%current-system)))) > (cond > ((not (nix-system->chez-machine system)) > #f) > ((target-arm64? system) > #f) > ((target-arm32? system) > (and (target-linux? system) > '())) > ((target-ppc32? system) > (and (target-linux? system) > '(threads))) > (else > '(threads)))) > --8<---------------cut here---------------end--------------->8--- Haven't tested this, but LGTM. > Alternatively, there could be an argument called something like > "variant", where the default would be 'upstream or maybe #f, and > supplying 'racket would always return '(threads). (Racket CS requires > the threaded version of Chez Scheme, so the chez-scheme-for-racket > has consistently added thread support immediately upon adding any new > target.) I don't think delegating to racket this soon is a good idea. > > And as a minor pet peeve, you ought to spell out machine. > > > > Ok, will do. > > > > > > +(define* (nix-system->chez-machine #:optional (system (%current- > > > system)) > > This should have been (or (%current-target-system) (%current- > system)). > > > > + #:key (threads? 'always)) > > > + "Return the Chez Scheme machine type corresponding to the Nix > > > system > > > +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to > > > a > > > Chez Scheme > > > +machine type is undefined. > > > + > > > +When THREADS? is @code{'always} (the default), the threaded > > > variant > > > of the > > > +machine type will be returned: note that the package returned by > > > +@code{chez-scheme-for-system} will always support native > > > threads. > > > When > > > +THREADS? is @code{#f}, the unthreaded machine type will be > > > returned. If > > > +THREADS? is @code{'upstream} (the default), the threaded variant > > > of > > > the > > > +machine type will be returned if and only if it is supported by > > > upstream Chez > > > +Scheme (see @code{chez-machine->upstream-restriction}). If > > > THREADS? > > > is any > > > +other value, an exception is raised." > > What's the point in having THREADS? 'always? In any case, assuming > > chez-machine-features is to be exported, this can easily be checked > > -- > > even if not, we can add the check internally by writing > > #:key (threads? (chez-supports-threads? system)) > > > > > + (let* ((hyphen (string-index system #\-)) > > > + (nix-arch (substring system 0 hyphen)) > > > + (nix-os (substring system (+ 1 hyphen))) > > > + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix- > > > arch)) > > > + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os)) > > > + (mach (and chez-arch chez-os (string-append chez-arch > > > chez- > > > os)))) > > This series of let-bindings should probably be done in a separate > > function called nix-system->chez-machine. > > On the one hand, the result of 'chez-scheme-for-system' will always > support threads, so being threaded by default is convenient. On the > other hand, it looks like I've reduced the use of this function (by > searching for files rather than coding in the machine type directory) > enough that it doesn't have a big impact either way. It will be more > important when we support cross-compilation, and I think we should > keep these functions internal and defer as much as possible of their > API design until then. > > For now, I think I'll say that it's unspecified whether the result is > a threaded or unthreaded machine type and add > `chez-machine->{un,}threaded` as needed. I think you can keep (chez-supports-threads? system) hidden even when using it to instantiate defaults. I currently don't see the relation between chez-scheme-for-system and nix-system->chez-machine, so if that's relevant, you'd have to clarify. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-17 7:24 ` Liliana Marie Prikler @ 2022-02-17 7:37 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 7:37 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/17/22 02:24, Liliana Marie Prikler wrote: > I currently don't see the relation > between chez-scheme-for-system and nix-system->chez-machine, so if > that's relevant, you'd have to clarify. It's relevant only in that, unless you as a user have done some transformation to specifically build an unthreaded variant, you will be using the threaded machine type. -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 05/11] gnu: Add stex. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-14 14:46 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 06/11] gnu: Add chez-nanopass Philip McGrath ` (5 subsequent siblings) 10 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New variable. (stex): Change from origin to package inheriting from 'stex-bootstrap'. (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove labels. Remove dependencies of stex-bootstrap. [inputs]: Remove labels. [arguments]: Adapt to use 'stex-bootstrap', 'search-input-file', and G-expressions. (nanopass): Make it public as a temporary workaround for Racket. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 430 ++++++++++++--------- gnu/packages/racket.scm | 5 +- 2 files changed, 258 insertions(+), 177 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index fc1da53178..945d1ce2ed 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -31,6 +31,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -191,113 +192,83 @@ (define* (nix-system->chez-machine #:optional (system (%current-system)) ;; Chez Scheme: ;; -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define unbundle-chez-submodules + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) +(define (unpack-nanopass+stex) + ;; delayed resolution of `nanopass` + #~(begin + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet unbundle-chez-submodules))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) + (native-inputs (list stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + #$(unpack-nanopass+stex))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -305,90 +276,59 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'install-symlink 'install-doc + (lambda* (#:key native-inputs inputs outputs + #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib (search-input-directory + (or native-inputs inputs) + "/lib/stex")) + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" + doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le @@ -412,3 +352,145 @@ (define* (stex-make #:optional (suffix "")) generates native code for each target processor, with support for x86, x86_64, and 32-bit PowerPC architectures.") (license license:asl2.0))) + +;; +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") ;; can run without compiling + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(nix-system->chez-machine + (or (%current-target-system) + (%current-system)))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license license:expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 865fdff70f..d8338bcd6f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) + ("stex" ,(package-source stex)) + ("nanopass" ,nanopass))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 05/11] gnu: Add stex. 2022-02-13 21:51 ` [bug#53878] [PATCH 05/11] gnu: Add stex Philip McGrath @ 2022-02-14 14:46 ` Liliana Marie Prikler [not found] ` <72f7937e-7476-a48c-56af-8f68834d4359@philipmcgrath.com> 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-14 14:46 UTC (permalink / raw) To: Philip McGrath, 53878 Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New > variable. > (stex): Change from origin to package inheriting from 'stex- > bootstrap'. > (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove > labels. Remove dependencies of stex-bootstrap. > [inputs]: Remove labels. > [arguments]: Adapt to use 'stex-bootstrap', 'search-input-file', and > G-expressions. > (nanopass): Make it public as a temporary workaround for Racket. > * gnu/packages/racket.scm > (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. This is again a large number of changes in one go. When it comes to writing good patches, less is more, especially in terms of being understandable. > +(define (unpack-nanopass+stex) > + ;; delayed resolution of `nanopass` > + #~(begin > + (copy-recursively #$nanopass > + "nanopass" > + #:keep-mtime? #t) > + (mkdir-p "stex") > + (with-output-to-file "stex/Mf-stex" > + (lambda () > + ;; otherwise, it will try to download submodules > + (display "# to placate ../configure"))))) > [...] > - (snippet > - ;; Remove bundled libraries. > - (with-imported-modules '((guix build utils)) > - #~(begin > - (use-modules (guix build utils)) > - (for-each (lambda (dir) > - (when (directory-exists? dir) > - (delete-file-recursively dir))) > - '("stex" > - "nanopass" > - "lz4" > - "zlib"))))))) > [...] > + (snippet unbundle-chez-submodules))) Why? > (build-system gnu-build-system) > (inputs > - `(("libuuid" ,util-linux "lib") > - ("zlib" ,zlib) > - ("lz4" ,lz4) > - ;; for expeditor: > - ("ncurses" ,ncurses) > - ;; for X11 clipboard support in expeditor: > - ;; > https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 > - ("libx11" ,libx11))) > - (native-inputs > - `(("nanopass" ,nanopass) ; source only > - ;; for docs > - ("stex" ,stex) > - ("xorg-rgb" ,xorg-rgb) > - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend > - texlive-epsf > - texlive-fonts-ec > - texlive-oberdiek))) > - ("ghostscript" ,ghostscript) > - ("netpbm" ,netpbm))) > + (list > + `(,util-linux "lib") ;<-- libuuid > + zlib > + lz4 > + ncurses ;<-- for expeditor > + ;; for X11 clipboard support in expeditor: > + ;; > https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 > + libx11)) > + (native-inputs (list stex-bootstrap)) This is a lot of noise. Either first clean up the inputs and then add new ones or the other way round, but doing both in the same commit (especially with other stuff as well) is too much imo. > (native-search-paths > (list (search-path-specification > (variable "CHEZSCHEMELIBDIRS") > (files (list (string-append "lib/chez-scheme")))))) > (outputs '("out" "doc")) > (arguments > - `(#:modules > - ((guix build gnu-build-system) > + (list > + #:modules > + '((guix build gnu-build-system) > (guix build utils) > (ice-9 ftw) > (ice-9 match)) > - #:test-target "test" > - #:configure-flags > - '("--threads") ;; TODO when we fix armhf, it doesn't support > --threads > - #:phases > - (modify-phases %standard-phases > - ;; put these where configure expects them to be > - (add-after 'unpack 'unpack-nanopass+stex > - (lambda* (#:key native-inputs inputs #:allow-other-keys) > - (for-each (lambda (dep) > - (define src > - (assoc-ref (or native-inputs inputs) > dep)) > - (copy-recursively src dep > - #:keep-mtime? #t)) > - '("nanopass" "stex")))) > - ;; NOTE: the custom Chez 'configure' script doesn't allow > - ;; unrecognized flags, such as those automatically added > - ;; by `gnu-build-system`. > - (replace 'configure > - (lambda* (#:key inputs outputs > - (configure-flags '()) > - #:allow-other-keys) > - (let* ((zlib-static (assoc-ref inputs "zlib:static")) > - (lz4-static (assoc-ref inputs "lz4:static")) > - (out (assoc-ref outputs "out")) > - ;; add flags which are always required: > - (flags (cons* (string-append "--installprefix=" > out) > + #:test-target "test" > + ;; TODO when we fix armhf, it may not support --threads > + #:configure-flags #~'("--threads") > + #:phases > + #~(modify-phases %standard-phases > + (add-after 'unpack 'unpack-nanopass+stex > + (lambda args > + #$(unpack-nanopass+stex))) > + ;; NOTE: the custom Chez 'configure' script doesn't allow > + ;; unrecognized flags, such as those automatically added > + ;; by `gnu-build-system`. > + (replace 'configure > + (lambda* (#:key inputs (configure-flags '()) #:allow- > other-keys) > + ;; add flags which are always required: > + (let ((flags (cons* (string-append "--installprefix=" > #$output) > "ZLIB=-lz" > "LZ4=-llz4" > "--libkernel" > @@ -305,90 +276,59 @@ (define src > ;; and letting Chez try causes an > error > "--nogzip-man-pages" > configure-flags))) > - (format #t "configure flags: ~s~%" flags) > - ;; Some makefiles (for tests) don't seem to propagate > CC > - ;; properly, so we take it out of their hands: > - (setenv "CC" ,(cc-for-target)) > - (setenv "HOME" "/tmp") > - (apply invoke > - "./configure" > - flags)))) > - ;; The binary file name is called "scheme" as is the one > from MIT/GNU > - ;; Scheme. We add a symlink to use in case both are > installed. > - (add-after 'install 'install-symlink > - (lambda* (#:key outputs #:allow-other-keys) > - (let* ((out (assoc-ref outputs "out")) > - (bin (string-append out "/bin")) > - (lib (string-append out "/lib")) > - (name "chez-scheme")) > - (symlink (string-append bin "/scheme") > - (string-append bin "/" name)) > - (map (lambda (file) > - (symlink file (string-append (dirname file) > - "/" name > ".boot"))) > - (find-files lib "scheme.boot"))))) > - ;; Building explicitly lets us avoid using substitute* > - ;; to re-write makefiles. > - (add-after 'install-symlink 'prepare-stex > - (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > - (let* ((stex+version > - (strip-store-file-name > - (assoc-ref (or native-inputs inputs) "stex"))) > - ;; Eventually we want to install stex as a real > - ;; package so it's reusable. For now: > - (stex-output "/tmp") > - (doc-dir (string-append stex-output > - "/share/doc/" > - stex+version))) > - (with-directory-excursion "stex" > - (invoke "make" > - "install" > - (string-append "LIB=" > - stex-output > - "/lib/" > - stex+version) > - (string-append "Scheme=" > - (assoc-ref outputs "out") > - "/bin/scheme")) > - (for-each (lambda (pth) > - (install-file pth doc-dir)) > - '("ReadMe" ; includes the license > - "doc/stex.html" > - "doc/stex.css" > - "doc/stex.pdf")))))) > - ;; Building the documentation requires stex and a running > scheme. > - ;; FIXME: this is probably wrong for cross-compilation > - (add-after 'prepare-stex 'install-doc > - (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > - (let* ((chez+version (strip-store-file-name > - (assoc-ref outputs "out"))) > - (stex+version > - (strip-store-file-name > - (assoc-ref (or native-inputs inputs) "stex"))) > - (scheme (string-append (assoc-ref outputs "out") > - "/bin/scheme")) > - ;; see note on stex-output in phase build-stex, > above: > - (stexlib (string-append "/tmp" > - "/lib/" > - stex+version)) > - (doc-dir (string-append (assoc-ref outputs > "doc") > - "/share/doc/" > - chez+version))) > - (define* (stex-make #:optional (suffix "")) > - (invoke "make" > - "install" > - (string-append "Scheme=" scheme) > - (string-append "STEXLIB=" stexlib) > - (string-append "installdir=" doc-dir > suffix))) > - (with-directory-excursion "csug" > - (stex-make "/csug")) > - (with-directory-excursion "release_notes" > - (stex-make "/release_notes")) > - (with-directory-excursion doc-dir > - (symlink "release_notes/release_notes.pdf" > - "release_notes.pdf") > - (symlink "csug/csug9_5.pdf" > - "csug.pdf")))))))) > + (format #t "configure flags: ~s~%" flags) > + ;; Some makefiles (for tests) don't seem to > propagate CC > + ;; properly, so we take it out of their hands: > + (setenv "CC" #$(cc-for-target)) > + (setenv "HOME" "/tmp") > + (apply invoke "./configure" flags)))) > + ;; The binary file name is called "scheme" as is the one > from > + ;; MIT/GNU Scheme. We add a symlink to use in case both > are > + ;; installed. > + (add-after 'install 'install-symlink > + (lambda* (#:key outputs #:allow-other-keys) > + (let* ((scheme (search-input-file outputs > "/bin/scheme")) > + (bin-dir (dirname scheme))) > + (symlink scheme > + (string-append bin-dir "/chez-scheme")) > + (match (find-files (string-append bin-dir "/../lib") > + "scheme.boot") > + ((scheme.boot) > + (symlink scheme.boot > + (string-append (dirname scheme.boot) > + "/chez- > scheme.boot"))))))) > + ;; Building the documentation requires stex and a running > scheme. > + ;; FIXME: this is probably wrong for cross-compilation > + (add-after 'install-symlink 'install-doc > + (lambda* (#:key native-inputs inputs outputs > + #:allow-other-keys) > + (match (assoc-ref outputs "doc") > + (#f > + (format #t "not installing docs~%")) > + (doc-prefix > + (let* ((chez+version (strip-store-file-name > #$output)) > + (scheme (search-input-file outputs > "/bin/scheme")) > + (stexlib (search-input-directory > + (or native-inputs inputs) > + "/lib/stex")) > + (doc-dir (string-append doc-prefix > + "/share/doc/" > + chez+version))) > + (define* (stex-make #:optional (suffix "")) > + (invoke "make" "install" > + (string-append "Scheme=" scheme) > + (string-append "STEXLIB=" stexlib) > + (string-append "installdir=" > + doc-dir suffix))) > + (with-directory-excursion "csug" > + (stex-make "/csug")) > + (with-directory-excursion "release_notes" > + (stex-make "/release_notes")) > + (with-directory-excursion doc-dir > + (symlink "release_notes/release_notes.pdf" > + "release_notes.pdf") > + (symlink "csug/csug9_5.pdf" > + "csug.pdf")))))))))) Again mixing cosmetic changes with functional ones. > ;; Chez Scheme does not have a MIPS backend. > ;; FIXME: Debian backports patches to get armhf working. > ;; We should too. It is the Chez machine type arm32le > @@ -412,3 +352,145 @@ (define* (stex-make #:optional (suffix "")) > generates native code for each target processor, with support for > x86, x86_64, > and 32-bit PowerPC architectures.") > (license license:asl2.0))) > + > +;; > +;; Chez's bootstrap dependencies: > +;; > + > +(define-public stex-bootstrap > + ;; This commit includes a fix which we would otherwise want to use > as > + ;; patch. Let's revert to tagged releases as soon as one becomes > available. > + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") > + (revision "1")) > + (hidden-package > + (package > + (name "stex") > + ;; ^ Debian calls this "stex", not "chez-stex". It is a set > of > + ;; command-line tools, and there isn't a Scheme API, let > alone a > + ;; Chez-specific one, except perhaps that the Scheme examples > are > + ;; assumed to be Chez-compatible. > + (version (git-version "1.2.2" revision commit)) > + (source > + (origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/dybvig/stex") > + (commit commit))) > + (sha256 > + (base32 > "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) > + (file-name (git-file-name name version)) > + (snippet > + #~(for-each delete-file > + '("sbin/install" "doc/stex.pdf" > "doc/stex.html"))))) > + (outputs '("out")) > + (build-system copy-build-system) > + ;; N.B. Upstream does not seem to support cross-compilation, > + ;; though it would probably be easy to add. > + (propagated-inputs > + (list xorg-rgb > + (texlive-updmap.cfg > + (list texlive-dvips-l3backend > + texlive-hyperref > + texlive-bibtex > + texlive-epsf > + texlive-fonts-ec > + texlive-oberdiek)) > + ghostscript > + netpbm)) > + ;; Debian uses a versionless path for STEXLIB, > + ;; which is much more convienient. > + (arguments > + (list > + #:install-plan #~`(("inputs" "lib/stex/") > + ("gifs" "lib/stex/") > + ("math" "lib/stex/") > + ("src" "lib/stex/") ;; can run without > compiling > + ("Mf-stex" "lib/stex/") > + ("Makefile.template" "lib/stex/")) > + #:phases > + #~(modify-phases %standard-phases > + (add-before 'install 'patch-sources > + (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > + (define scheme > + (false-if-exception > + (search-input-file inputs "/bin/scheme"))) > + (when scheme > + (setenv "Scheme" scheme)) > + (substitute* '("Makefile.template" > + "doc/Makefile") > + (("STEXLIB=[^\n]*") > + (string-append "STEXLIB=" #$output "/lib/stex")) > + (("Scheme=[^\n]*") > + (string-append "Scheme=" (or scheme "scheme")))) > + (substitute* '("Mf-stex" > + "math/Makefile") > + (("/bin/rm") > + "rm")) > + (substitute* "Mf-stex" > + (("SHELL=bash") > + ;; avoid Solaris workaround > + "#SHELL=bash")))) > + (add-after 'install 'maybe-compile > + (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > + (cond > + ((getenv "Scheme") > + => (lambda (scheme) > + (define makefile > + (string-append (getcwd) "/Makefile")) > + (define machine > + #$(nix-system->chez-machine > + (or (%current-target-system) > + (%current-system)))) > + (with-directory-excursion > + (search-input-directory outputs > "/lib/stex") > + (invoke "make" > + "-f" makefile > + (string-append "Scheme=" scheme)) > + (for-each delete-file > + (find-files machine "\\."))))) > + (else > + (format #t "not compiling~%"))))) > + (add-after 'maybe-compile 'maybe-make-docs > + (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > + (cond > + ((assoc-ref outputs "doc") > + => (lambda (doc-prefix) > + (define doc-dir > + (string-append doc-prefix > "/share/doc/stex")) > + ;; the Makefile is referenced in the > documentation > + (copy-recursively "doc" doc-dir) > + (install-file "ReadMe" doc-dir) > + (with-directory-excursion "doc" > + (invoke "make") > + (install-file "stex.html" doc-dir) > + (install-file "stex.pdf" doc-dir)))) > + (else > + (format #t "not making docs~%")))))))) > + (home-page "https://github.com/dybvig/stex") > + (synopsis "LaTeX with embeded Scheme code and HTML > generation") > + (description "The @code{stex} package extends LaTeX with a > handful of > +commands for including Scheme code (or pretty much any other kind of > code, as > +long as you don't plan to use the Scheme-specific transcript > support) in a > +document. It provides the programs @code{scheme-prep} and > @code{html-prep} to > +convert @code{stex} documents to LaTeX and HTML, respectively, plus > makefile > +templates, style files, and other resources. The @code{stex} system > is used > +to typeset @cite{The Scheme Programming Language} and the @cite{Chez > Scheme > +User's Guix}, among other documents.") > + (license license:expat))))) > + > +(define-public stex > + (package/inherit stex-bootstrap > + (inputs (modify-inputs (package-inputs stex-bootstrap) > + (prepend chez-scheme))) > + (outputs '("out" "doc")) > + (properties '()))) > + > +(define-public nanopass > + (let ((version "1.9.2")) > + (origin > + (method git-fetch) > + (uri (git-reference > + (url > "https://github.com/nanopass/nanopass-framework-scheme") > + (commit (string-append "v" version)))) > + (sha256 (base32 > "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) > + (file-name (git-file-name "nanopass" version))))) > diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm > index 865fdff70f..d8338bcd6f 100644 > --- a/gnu/packages/racket.scm > +++ b/gnu/packages/racket.scm > @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles > `(("racket" ,(if (%current-target-system) > racket-minimal > racket-minimal-bc-3m)) > - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) > "stex")) > - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) > - "nanopass")))) > + ("stex" ,(package-source stex)) > + ("nanopass" ,nanopass))) > (arguments > `(#:phases > (modify-phases %standard-phases Not quite sure on these hunks. Could be fine, could not be fine. Disentangling stex from chez and publicly exporting it is probably a good idea, though. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
[parent not found: <72f7937e-7476-a48c-56af-8f68834d4359@philipmcgrath.com>]
* [bug#53878] [PATCH 05/11] gnu: Add stex. [not found] ` <72f7937e-7476-a48c-56af-8f68834d4359@philipmcgrath.com> @ 2022-02-16 20:46 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-16 20:46 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/16/22 13:35, Philip McGrath wrote: > Hi, > > On 2/14/22 09:46, Liliana Marie Prikler wrote: >> Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >>> * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New >>> variable. >>> (stex): Change from origin to package inheriting from 'stex- >>> bootstrap'. >>> (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove >>> labels. Remove dependencies of stex-bootstrap. >>> [inputs]: Remove labels. >>> [arguments]: Adapt to use 'stex-bootstrap', 'search-input-file', and >>> G-expressions. >>> (nanopass): Make it public as a temporary workaround for Racket. >>> * gnu/packages/racket.scm >>> (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. >> This is again a large number of changes in one go. When it comes to >> writing good patches, less is more, especially in terms of being >> understandable. I will separate the non-substantive changes to input labels and such as discussed below. >>> +(define (unpack-nanopass+stex) >>> + ;; delayed resolution of `nanopass` >>> + #~(begin >>> + (copy-recursively #$nanopass >>> + "nanopass" >>> + #:keep-mtime? #t) >>> + (mkdir-p "stex") >>> + (with-output-to-file "stex/Mf-stex" >>> + (lambda () >>> + ;; otherwise, it will try to download submodules >>> + (display "# to placate ../configure"))))) >>> [...] >>> - (snippet >>> - ;; Remove bundled libraries. >>> - (with-imported-modules '((guix build utils)) >>> - #~(begin >>> - (use-modules (guix build utils)) >>> - (for-each (lambda (dir) >>> - (when (directory-exists? dir) >>> - (delete-file-recursively dir))) >>> - '("stex" >>> - "nanopass" >>> - "lz4" >>> - "zlib"))))))) >>> [...] >>> + (snippet unbundle-chez-submodules))) >> Why? Why lift the snippet to `unbundle-chez-submodules`? The origin of Racket also needs it, but wrapped in a `with-directory-excursion`. >> >>> (build-system gnu-build-system) >>> (inputs >>> - `(("libuuid" ,util-linux "lib") >>> - ("zlib" ,zlib) >>> - ("lz4" ,lz4) >>> - ;; for expeditor: >>> - ("ncurses" ,ncurses) >>> - ;; for X11 clipboard support in expeditor: >>> - ;; >>> https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 >>> - ("libx11" ,libx11))) >>> - (native-inputs >>> - `(("nanopass" ,nanopass) ; source only >>> - ;; for docs >>> - ("stex" ,stex) >>> - ("xorg-rgb" ,xorg-rgb) >>> - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend >>> - texlive-epsf >>> - texlive-fonts-ec >>> - texlive-oberdiek))) >>> - ("ghostscript" ,ghostscript) >>> - ("netpbm" ,netpbm))) >>> + (list >>> + `(,util-linux "lib") ;<-- libuuid >>> + zlib >>> + lz4 >>> + ncurses ;<-- for expeditor >>> + ;; for X11 clipboard support in expeditor: >>> + ;; >>> https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 >>> + libx11)) >>> + (native-inputs (list stex-bootstrap)) >> This is a lot of noise. Either first clean up the inputs and then add >> new ones or the other way round, but doing both in the same commit >> (especially with other stuff as well) is too much imo. Ok, I will clean the inputs before lifting out stex. >> >>> (native-search-paths >>> (list (search-path-specification >>> (variable "CHEZSCHEMELIBDIRS") >>> (files (list (string-append "lib/chez-scheme")))))) >>> (outputs '("out" "doc")) >>> (arguments >>> - `(#:modules >>> - ((guix build gnu-build-system) >>> + (list >>> + #:modules >>> + '((guix build gnu-build-system) >>> (guix build utils) >>> (ice-9 ftw) >>> (ice-9 match)) >>> - #:test-target "test" >>> - #:configure-flags >>> - '("--threads") ;; TODO when we fix armhf, it doesn't support >>> --threads >>> - #:phases >>> - (modify-phases %standard-phases >>> - ;; put these where configure expects them to be >>> - (add-after 'unpack 'unpack-nanopass+stex >>> - (lambda* (#:key native-inputs inputs #:allow-other-keys) >>> - (for-each (lambda (dep) >>> - (define src >>> - (assoc-ref (or native-inputs inputs) >>> dep)) >>> - (copy-recursively src dep >>> - #:keep-mtime? #t)) >>> - '("nanopass" "stex")))) >>> - ;; NOTE: the custom Chez 'configure' script doesn't allow >>> - ;; unrecognized flags, such as those automatically added >>> - ;; by `gnu-build-system`. >>> - (replace 'configure >>> - (lambda* (#:key inputs outputs >>> - (configure-flags '()) >>> - #:allow-other-keys) >>> - (let* ((zlib-static (assoc-ref inputs "zlib:static")) >>> - (lz4-static (assoc-ref inputs "lz4:static")) >>> - (out (assoc-ref outputs "out")) >>> - ;; add flags which are always required: >>> - (flags (cons* (string-append "--installprefix=" >>> out) >>> + #:test-target "test" >>> + ;; TODO when we fix armhf, it may not support --threads >>> + #:configure-flags #~'("--threads") >>> + #:phases >>> + #~(modify-phases %standard-phases >>> + (add-after 'unpack 'unpack-nanopass+stex >>> + (lambda args >>> + #$(unpack-nanopass+stex))) >>> + ;; NOTE: the custom Chez 'configure' script doesn't allow >>> + ;; unrecognized flags, such as those automatically added >>> + ;; by `gnu-build-system`. >>> + (replace 'configure >>> + (lambda* (#:key inputs (configure-flags '()) #:allow- >>> other-keys) >>> + ;; add flags which are always required: >>> + (let ((flags (cons* (string-append "--installprefix=" >>> #$output) >>> "ZLIB=-lz" >>> "LZ4=-llz4" >>> "--libkernel" >>> @@ -305,90 +276,59 @@ (define src >>> ;; and letting Chez try causes an >>> error >>> "--nogzip-man-pages" >>> configure-flags))) >>> - (format #t "configure flags: ~s~%" flags) >>> - ;; Some makefiles (for tests) don't seem to propagate >>> CC >>> - ;; properly, so we take it out of their hands: >>> - (setenv "CC" ,(cc-for-target)) >>> - (setenv "HOME" "/tmp") >>> - (apply invoke >>> - "./configure" >>> - flags)))) >>> - ;; The binary file name is called "scheme" as is the one >>> from MIT/GNU >>> - ;; Scheme. We add a symlink to use in case both are >>> installed. >>> - (add-after 'install 'install-symlink >>> - (lambda* (#:key outputs #:allow-other-keys) >>> - (let* ((out (assoc-ref outputs "out")) >>> - (bin (string-append out "/bin")) >>> - (lib (string-append out "/lib")) >>> - (name "chez-scheme")) >>> - (symlink (string-append bin "/scheme") >>> - (string-append bin "/" name)) >>> - (map (lambda (file) >>> - (symlink file (string-append (dirname file) >>> - "/" name >>> ".boot"))) >>> - (find-files lib "scheme.boot"))))) >>> - ;; Building explicitly lets us avoid using substitute* >>> - ;; to re-write makefiles. >>> - (add-after 'install-symlink 'prepare-stex >>> - (lambda* (#:key native-inputs inputs outputs #:allow- >>> other-keys) >>> - (let* ((stex+version >>> - (strip-store-file-name >>> - (assoc-ref (or native-inputs inputs) "stex"))) >>> - ;; Eventually we want to install stex as a real >>> - ;; package so it's reusable. For now: >>> - (stex-output "/tmp") >>> - (doc-dir (string-append stex-output >>> - "/share/doc/" >>> - stex+version))) >>> - (with-directory-excursion "stex" >>> - (invoke "make" >>> - "install" >>> - (string-append "LIB=" >>> - stex-output >>> - "/lib/" >>> - stex+version) >>> - (string-append "Scheme=" >>> - (assoc-ref outputs "out") >>> - "/bin/scheme")) >>> - (for-each (lambda (pth) >>> - (install-file pth doc-dir)) >>> - '("ReadMe" ; includes the license >>> - "doc/stex.html" >>> - "doc/stex.css" >>> - "doc/stex.pdf")))))) >>> - ;; Building the documentation requires stex and a running >>> scheme. >>> - ;; FIXME: this is probably wrong for cross-compilation >>> - (add-after 'prepare-stex 'install-doc >>> - (lambda* (#:key native-inputs inputs outputs #:allow- >>> other-keys) >>> - (let* ((chez+version (strip-store-file-name >>> - (assoc-ref outputs "out"))) >>> - (stex+version >>> - (strip-store-file-name >>> - (assoc-ref (or native-inputs inputs) "stex"))) >>> - (scheme (string-append (assoc-ref outputs "out") >>> - "/bin/scheme")) >>> - ;; see note on stex-output in phase build-stex, >>> above: >>> - (stexlib (string-append "/tmp" >>> - "/lib/" >>> - stex+version)) >>> - (doc-dir (string-append (assoc-ref outputs >>> "doc") >>> - "/share/doc/" >>> - chez+version))) >>> - (define* (stex-make #:optional (suffix "")) >>> - (invoke "make" >>> - "install" >>> - (string-append "Scheme=" scheme) >>> - (string-append "STEXLIB=" stexlib) >>> - (string-append "installdir=" doc-dir >>> suffix))) >>> - (with-directory-excursion "csug" >>> - (stex-make "/csug")) >>> - (with-directory-excursion "release_notes" >>> - (stex-make "/release_notes")) >>> - (with-directory-excursion doc-dir >>> - (symlink "release_notes/release_notes.pdf" >>> - "release_notes.pdf") >>> - (symlink "csug/csug9_5.pdf" >>> - "csug.pdf")))))))) >>> + (format #t "configure flags: ~s~%" flags) >>> + ;; Some makefiles (for tests) don't seem to >>> propagate CC >>> + ;; properly, so we take it out of their hands: >>> + (setenv "CC" #$(cc-for-target)) >>> + (setenv "HOME" "/tmp") >>> + (apply invoke "./configure" flags)))) >>> + ;; The binary file name is called "scheme" as is the one >>> from >>> + ;; MIT/GNU Scheme. We add a symlink to use in case both >>> are >>> + ;; installed. >>> + (add-after 'install 'install-symlink >>> + (lambda* (#:key outputs #:allow-other-keys) >>> + (let* ((scheme (search-input-file outputs >>> "/bin/scheme")) >>> + (bin-dir (dirname scheme))) >>> + (symlink scheme >>> + (string-append bin-dir "/chez-scheme")) >>> + (match (find-files (string-append bin-dir "/../lib") >>> + "scheme.boot") >>> + ((scheme.boot) >>> + (symlink scheme.boot >>> + (string-append (dirname scheme.boot) >>> + "/chez- >>> scheme.boot"))))))) >>> + ;; Building the documentation requires stex and a running >>> scheme. >>> + ;; FIXME: this is probably wrong for cross-compilation >>> + (add-after 'install-symlink 'install-doc >>> + (lambda* (#:key native-inputs inputs outputs >>> + #:allow-other-keys) >>> + (match (assoc-ref outputs "doc") >>> + (#f >>> + (format #t "not installing docs~%")) >>> + (doc-prefix >>> + (let* ((chez+version (strip-store-file-name >>> #$output)) >>> + (scheme (search-input-file outputs >>> "/bin/scheme")) >>> + (stexlib (search-input-directory >>> + (or native-inputs inputs) >>> + "/lib/stex")) >>> + (doc-dir (string-append doc-prefix >>> + "/share/doc/" >>> + chez+version))) >>> + (define* (stex-make #:optional (suffix "")) >>> + (invoke "make" "install" >>> + (string-append "Scheme=" scheme) >>> + (string-append "STEXLIB=" stexlib) >>> + (string-append "installdir=" >>> + doc-dir suffix))) >>> + (with-directory-excursion "csug" >>> + (stex-make "/csug")) >>> + (with-directory-excursion "release_notes" >>> + (stex-make "/release_notes")) >>> + (with-directory-excursion doc-dir >>> + (symlink "release_notes/release_notes.pdf" >>> + "release_notes.pdf") >>> + (symlink "csug/csug9_5.pdf" >>> + "csug.pdf")))))))))) >> Again mixing cosmetic changes with functional ones. Ok, I separate these. >>> @@ -412,3 +352,145 @@ (define* (stex-make #:optional (suffix "")) >>> generates native code for each target processor, with support for >>> x86, x86_64, >>> and 32-bit PowerPC architectures.") >>> (license license:asl2.0))) >>> + >>> +;; >>> +;; Chez's bootstrap dependencies: >>> +;; ... >> Not quite sure on these hunks. Could be fine, could not be fine. >> Disentangling stex from chez and publicly exporting it is probably a >> good idea, though. Especially because it is also needed to build the docs for nanopass, itself, and at least one package not yet in Guix (<https://github.com/becls/swish>). -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 06/11] gnu: Add chez-nanopass. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 05/11] gnu: Add stex Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (4 subsequent siblings) 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-scheme)[native-inputs]: Add it. (chez-nanopass): New variable. (unpack-nanopass+stex): Adapt accordingly. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 97 ++++++++++++++++++---- gnu/packages/racket.scm | 2 +- 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 945d1ce2ed..90fd63b5ae 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -203,12 +203,13 @@ (define unbundle-chez-submodules "lz4" "zlib")))) -(define (unpack-nanopass+stex) - ;; delayed resolution of `nanopass` +(define unpack-nanopass+stex #~(begin - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) (mkdir-p "stex") (with-output-to-file "stex/Mf-stex" (lambda () @@ -241,7 +242,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -261,7 +262,7 @@ (define-public chez-scheme #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args - #$(unpack-nanopass+stex))) + #$unpack-nanopass+stex)) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -485,12 +486,76 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license license:expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d8338bcd6f..e8d016c07b 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -334,7 +334,7 @@ (define-public racket-bootstrap-chez-bootfiles racket-minimal racket-minimal-bc-3m)) ("stex" ,(package-source stex)) - ("nanopass" ,nanopass))) + ("nanopass" ,(package-source chez-nanopass)))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 06/11] gnu: Add chez-nanopass Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-14 14:54 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket Philip McGrath ` (3 subsequent siblings) 10 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath This might seem a bit silly in isolation, but it makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]: Add new phase 'unpack-bootfiles'. [version, source, home-page]: Derive from 'chez-scheme-bootstrap-bootfiles'. --- gnu/packages/chez-and-racket-bootstrap.scm | 57 ++++++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 90fd63b5ae..38708ab690 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -216,9 +216,9 @@ (define unpack-nanopass+stex ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) -(define-public chez-scheme +(define-public chez-scheme-bootstrap-bootfiles (package - (name "chez-scheme") + (name "chez-scheme-bootstrap-bootfiles") ;; The version should match `(scheme-version-number)`. ;; See s/cmacros.ss c. line 360. (version "9.5.6") @@ -230,8 +230,45 @@ (define-public chez-scheme (sha256 (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) + (file-name (git-file-name "chez-scheme" version)) (snippet unbundle-chez-submodules))) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((mach (nix-system->chez-machine system #:threads? #f))) + (or (equal? "arm32le" mach) + (and mach + (member (substring mach 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> mach) + '("le" "nt" "osx")))))) + %supported-systems)) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source.") + (properties `((hidden? . #t))) + (license license:asl2.0))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version (package-version chez-scheme-bootstrap-bootfiles)) + (source (package-source chez-scheme-bootstrap-bootfiles)) (build-system gnu-build-system) (inputs (list @@ -242,7 +279,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -263,6 +302,14 @@ (define-public chez-scheme (add-after 'unpack 'unpack-nanopass+stex (lambda args #$unpack-nanopass+stex)) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -345,7 +392,7 @@ (define* (stex-make #:optional (suffix "")) (not (eq? 'no-support (chez-machine->upstream-restriction mach)))))) %supported-systems))) - (home-page "https://cisco.github.io/ChezScheme/") + (home-page (package-home-page chez-scheme-bootstrap-bootfiles)) (synopsis "R6RS Scheme compiler and run-time") (description "Chez Scheme is a compiler and run-time system for the language of the -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-13 21:51 ` [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-14 14:54 ` Liliana Marie Prikler 2022-02-16 21:13 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-14 14:54 UTC (permalink / raw) To: Philip McGrath, 53878 Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > This might seem a bit silly in isolation, but it makes the structure > of the upstream Chez Scheme package the same as for the Racket > variant, it sets things up for (one day, hopefully) actually being > able to bootstrap the upstream Chez Scheme bootfiles, and it may be > useful for cross-compilation and adding support for architectures > without pre-built bootfiles from upstream. > > * gnu/packages/chez-and-racket-bootstrap.scm > (chez-scheme-bootstrap-bootfiles): New variable. > (chez-scheme)[native-inputs]: Add it. > [arguments]: Add new phase 'unpack-bootfiles'. > [version, source, home-page]: Derive from 'chez-scheme-bootstrap- > bootfiles'. > --- While having chez-scheme-bootstrap-bootfiles (silly name) does make some kind of sense, making chez-scheme inherit from it does not. Given that we don't have a chez-scheme bootstrap tower at hand, you should probably make (chez-scheme-bootstrap) a procedure which takes chez- scheme's origin as argument and returns the full package. Also, while technically a violation of the DRY principle, you are allowed to type out the homepage multiple times. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-14 14:54 ` Liliana Marie Prikler @ 2022-02-16 21:13 ` Philip McGrath 2022-02-17 7:10 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-16 21:13 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/14/22 09:54, Liliana Marie Prikler wrote: > Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >> This might seem a bit silly in isolation, but it makes the structure >> of the upstream Chez Scheme package the same as for the Racket >> variant, it sets things up for (one day, hopefully) actually being >> able to bootstrap the upstream Chez Scheme bootfiles, and it may be >> useful for cross-compilation and adding support for architectures >> without pre-built bootfiles from upstream. >> >> * gnu/packages/chez-and-racket-bootstrap.scm >> (chez-scheme-bootstrap-bootfiles): New variable. >> (chez-scheme)[native-inputs]: Add it. >> [arguments]: Add new phase 'unpack-bootfiles'. >> [version, source, home-page]: Derive from 'chez-scheme-bootstrap- >> bootfiles'. >> --- > While having chez-scheme-bootstrap-bootfiles (silly name) does make > some kind of sense, making chez-scheme inherit from it does not. Given > that we don't have a chez-scheme bootstrap tower at hand, you should > probably make (chez-scheme-bootstrap) a procedure which takes chez- > scheme's origin as argument and returns the full package. > Making a function is an interesting idea, but I'm not sure I'm quite picturing what you have in mind. I will see if I can figure out something that seems reasonable as I revise this series, if I don't hear from you before then. One reason I like making the bootfiles a package is that a set of bootfiles includes artifacts in addition to the bootfiles themselves, such as generated C headers describing the layout of Scheme objects in memory, some of which are not included as part of an installed Chez Scheme. For example, imagine someone wants to run Chez Scheme on FreeBSD: upstream does not distribute BSD bootfiles, so they must be cross-compiled. Even though Guix doesn't have a C toolchain for FreeBSD (AFAIK), Guix could be used to reproducibly build the needed bootfiles and pack a "source" tarball to be used on a FreeBSD build machine. Also, the process for building bootfiles is largely orthogonal to building the actual `scheme` executable, and it seems like eventually it may be useful to be able to override options separately. There may be other ways to address these sorts of things, and it's true that a lot of this has more to do with my intuition of what might be work well in the future, rather than something that actually works right now. Is there a technical reason to prefer either repeating the home page, license, etc. or writing e.g. `(package-license chez-scheme-bootstrap-bootfiles)` rather than using inheritance? -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-16 21:13 ` Philip McGrath @ 2022-02-17 7:10 ` Liliana Marie Prikler 2022-02-17 8:06 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-17 7:10 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Mittwoch, dem 16.02.2022 um 16:13 -0500 schrieb Philip McGrath: > Hi, > > On 2/14/22 09:54, Liliana Marie Prikler wrote: > > Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > > > This might seem a bit silly in isolation, but it makes the > > > structure of the upstream Chez Scheme package the same as for the > > > Racket variant, it sets things up for (one day, hopefully) > > > actually being able to bootstrap the upstream Chez Scheme > > > bootfiles, and it may be useful for cross-compilation and adding > > > support for architectures without pre-built bootfiles from > > > upstream. > > > > > > * gnu/packages/chez-and-racket-bootstrap.scm > > > (chez-scheme-bootstrap-bootfiles): New variable. > > > (chez-scheme)[native-inputs]: Add it. > > > [arguments]: Add new phase 'unpack-bootfiles'. > > > [version, source, home-page]: Derive from 'chez-scheme-bootstrap- > > > bootfiles'. > > > --- > > While having chez-scheme-bootstrap-bootfiles (silly name) does make > > some kind of sense, making chez-scheme inherit from it does not. > > Given that we don't have a chez-scheme bootstrap tower at hand, you > > should probably make (chez-scheme-bootstrap) a procedure which > > takes chez-scheme's origin as argument and returns the full > > package. > > > Making a function is an interesting idea, but I'm not sure I'm quite > picturing what you have in mind. I will see if I can figure out > something that seems reasonable as I revise this series, if I don't > hear from you before then. I was picturing something like (define chez-bootfiles (chez ...) (package/inherit chez (inputs ...) (native-inputs ...) (build-system ...) (arguments ...))) > One reason I like making the bootfiles a package is that a set of > bootfiles includes artifacts in addition to the bootfiles themselves, > such as generated C headers describing the layout of Scheme objects > in memory, some of which are not included as part of an installed > Chez Scheme. For example, imagine someone wants to run Chez Scheme on > FreeBSD: upstream does not distribute BSD bootfiles, so they must be > cross-compiled. Even though Guix doesn't have a C toolchain for > FreeBSD (AFAIK), Guix could be used to reproducibly build the needed > bootfiles and pack a "source" tarball to be used on a FreeBSD build > machine. > > Also, the process for building bootfiles is largely orthogonal to > building the actual `scheme` executable, and it seems like eventually > it may be useful to be able to override options separately. Again, I'm with you on making chez-bootfiles a package and your rationale sounds reasonable, but I don't think it's correct to say that chez inherits from them. IIUC it is rather the other way around; the bootfiles contain precompiled versions of Chez among other things. > Is there a technical reason to prefer either repeating the home page, > license, etc. or writing e.g. `(package-license > chez-scheme-bootstrap-bootfiles)` rather than using inheritance? You should not write (package-license chez-scheme-bootstrap-files), that's the point! For one, that's exactly what inheritance would do unless you specify the field (technical reason), but more importantly, as a reader, using (package-license this-other-chez-thing) sends me on a journey to track down this-other-chez-thing while determining the license of chez! That's just silly (social reason). Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 7:10 ` Liliana Marie Prikler @ 2022-02-17 8:06 ` Philip McGrath 2022-02-17 8:19 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 8:06 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/17/22 02:10, Liliana Marie Prikler wrote: > Hi, > > Am Mittwoch, dem 16.02.2022 um 16:13 -0500 schrieb Philip McGrath: >> Hi, >> >> On 2/14/22 09:54, Liliana Marie Prikler wrote: >>> Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >>>> This might seem a bit silly in isolation, but it makes the >>>> structure of the upstream Chez Scheme package the same as for the >>>> Racket variant, it sets things up for (one day, hopefully) >>>> actually being able to bootstrap the upstream Chez Scheme >>>> bootfiles, and it may be useful for cross-compilation and adding >>>> support for architectures without pre-built bootfiles from >>>> upstream. >>>> >>>> * gnu/packages/chez-and-racket-bootstrap.scm >>>> (chez-scheme-bootstrap-bootfiles): New variable. >>>> (chez-scheme)[native-inputs]: Add it. >>>> [arguments]: Add new phase 'unpack-bootfiles'. >>>> [version, source, home-page]: Derive from 'chez-scheme-bootstrap- >>>> bootfiles'. >>>> --- >>> While having chez-scheme-bootstrap-bootfiles (silly name) does make >>> some kind of sense, making chez-scheme inherit from it does not. >>> Given that we don't have a chez-scheme bootstrap tower at hand, you >>> should probably make (chez-scheme-bootstrap) a procedure which >>> takes chez-scheme's origin as argument and returns the full >>> package. >>> >> Making a function is an interesting idea, but I'm not sure I'm quite >> picturing what you have in mind. I will see if I can figure out >> something that seems reasonable as I revise this series, if I don't >> hear from you before then. > I was picturing something like > > (define chez-bootfiles (chez ...) > (package/inherit chez > (inputs ...) > (native-inputs ...) > (build-system ...) > (arguments ...))) > Sorry, I still don't think I'm following. Would this rely on the `mative-inputs` being thunked to let the result of this function be an input to `chez-scheme`? What commonality is the function abstracting over, compared to having 'chez-scheme-for-racket-bootstrap-bootfiles' inherit from 'chez-scheme-bootstrap-bootfiles'? (I'm using "-bootstrap-bootfiles" because there are also other kinds of bootfiles: applications can create their own bootfiles, e.g. "racket.boot", and using Chez as a cross-compiler also involves more bootfiles.) >> Is there a technical reason to prefer either repeating the home page, >> license, etc. or writing e.g. `(package-license >> chez-scheme-bootstrap-bootfiles)` rather than using inheritance? > You should not write (package-license chez-scheme-bootstrap-files), > that's the point! For one, that's exactly what inheritance would do > unless you specify the field (technical reason), but more importantly, > as a reader, using (package-license this-other-chez-thing) sends me on > a journey to track down this-other-chez-thing while determining the > license of chez! That's just silly (social reason). That makes some sense with respect to the license and home page, but what about 'package-source' and 'package-version'? -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 8:06 ` Philip McGrath @ 2022-02-17 8:19 ` Liliana Marie Prikler 2022-02-17 8:40 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-17 8:19 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Donnerstag, dem 17.02.2022 um 03:06 -0500 schrieb Philip McGrath: > Hi, > > On 2/17/22 02:10, Liliana Marie Prikler wrote: > > [...] > > I was picturing something like > > > > (define chez-bootfiles (chez ...) > > (package/inherit chez > > (inputs ...) > > (native-inputs ...) > > (build-system ...) > > (arguments ...))) > > > > Sorry, I still don't think I'm following. Would this rely on the > `mative-inputs` being thunked to let the result of this function be > an input to `chez-scheme`? Yes. > What commonality is the function abstracting over, compared to having > 'chez-scheme-for-racket-bootstrap-bootfiles' inherit from 'chez- > scheme-bootstrap-bootfiles'? At the moment version, source, home-page and license. I don't really think bootstrap files ought to be a part of chez' source, so if you wanted to do this really cleanly, you'd have to drop them from chez and add restrict chez-bootstrap to them, which would imply you'd have to use (version (package-version chez-scheme)) explicitly – for now I don't want to add too much burden to that patch and you can assume source to be the same between the two. > (I'm using "-bootstrap-bootfiles" because there are also other kinds > of bootfiles: applications can create their own bootfiles, e.g. > "racket.boot", and using Chez as a cross-compiler also involves more > bootfiles.) I have no idea how useful that feature is or how widely it is used, but if those are just binary blobs needed to get chez scheme running, we ought to treat them as that. That makes some sense with respect to the license and home page, but > > > That makes some sense with respect to the license and home page, but > what about 'package-source' and 'package-version'? Your patch currently makes them the same for both, so you tell me :P See above for long-term plans. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 8:19 ` Liliana Marie Prikler @ 2022-02-17 8:40 ` Philip McGrath 2022-02-17 8:46 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 8:40 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/17/22 03:19, Liliana Marie Prikler wrote: > Hi, > > Am Donnerstag, dem 17.02.2022 um 03:06 -0500 schrieb Philip McGrath: >> Hi, >> >> On 2/17/22 02:10, Liliana Marie Prikler wrote: >>> [...] >>> I was picturing something like >>> >>> (define chez-bootfiles (chez ...) >>> (package/inherit chez >>> (inputs ...) >>> (native-inputs ...) >>> (build-system ...) >>> (arguments ...))) >>> >> >> Sorry, I still don't think I'm following. Would this rely on the >> `mative-inputs` being thunked to let the result of this function be >> an input to `chez-scheme`? > Yes. > >> What commonality is the function abstracting over, compared to having >> 'chez-scheme-for-racket-bootstrap-bootfiles' inherit from 'chez- >> scheme-bootstrap-bootfiles'? > At the moment version, source, home-page and license. I don't really > think bootstrap files ought to be a part of chez' source, so if you > wanted to do this really cleanly, you'd have to drop them from chez and > add restrict chez-bootstrap to them, which would imply you'd have to > use (version (package-version chez-scheme)) explicitly – for now I > don't want to add too much burden to that patch and you can assume > source to be the same between the two. > Ok, this helps, I think. I'll give it a try. In <https://issues.guix.gnu.org/47153#9> you argued---and convinced me---that we should keep the pre-built bootfiles in the origin until we actually don't need them. With 'chez-scheme-for-racket', that's already true, and there aren't bootfiles in that origin anyway. When someday we can actually bootstrap upstream Chez Scheme, presumably we'll add a snippet to delete the pre-built bootfiles from the origin, at which point the it will still be the same origin for both. -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 8:40 ` Philip McGrath @ 2022-02-17 8:46 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-17 8:46 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Donnerstag, dem 17.02.2022 um 03:40 -0500 schrieb Philip McGrath: > Hi, > > On 2/17/22 03:19, Liliana Marie Prikler wrote: > > Hi, > > > > Am Donnerstag, dem 17.02.2022 um 03:06 -0500 schrieb Philip > > McGrath: > > > Hi, > > > > > > On 2/17/22 02:10, Liliana Marie Prikler wrote: > > > > [...] > > > > I was picturing something like > > > > > > > > (define chez-bootfiles (chez ...) > > > > (package/inherit chez > > > > (inputs ...) > > > > (native-inputs ...) > > > > (build-system ...) > > > > (arguments ...))) > > > > > > > > > > Sorry, I still don't think I'm following. Would this rely on the > > > `mative-inputs` being thunked to let the result of this function > > > be > > > an input to `chez-scheme`? > > Yes. > > > > > What commonality is the function abstracting over, compared to > > > having > > > 'chez-scheme-for-racket-bootstrap-bootfiles' inherit from 'chez- > > > scheme-bootstrap-bootfiles'? > > At the moment version, source, home-page and license. I don't > > really > > think bootstrap files ought to be a part of chez' source, so if you > > wanted to do this really cleanly, you'd have to drop them from chez > > and > > add restrict chez-bootstrap to them, which would imply you'd have > > to > > use (version (package-version chez-scheme)) explicitly – for now I > > don't want to add too much burden to that patch and you can assume > > source to be the same between the two. > > > > Ok, this helps, I think. I'll give it a try. > > In <https://issues.guix.gnu.org/47153#9> you argued---and convinced > me---that we should keep the pre-built bootfiles in the origin until > we actually don't need them. With 'chez-scheme-for-racket', that's > already true, and there aren't bootfiles in that origin anyway. When > someday we can actually bootstrap upstream Chez Scheme, presumably > we'll add a snippet to delete the pre-built bootfiles from the > origin, at which point the it will still be the same origin for both. This concerns schez-scheme-for-racket, not the current chez-scheme for which we are packaging the bootfiles, am I right? Given that we build a set of bootfiles that would be enough to go forward, we no longer need the original bootfiles beyond that point, i.e. the "bootstrap bootfiles" would only be needed inside chez-bootstrap, but not chez itself (which can instead use the native-input). Am I missing something here? ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-17 8:46 ` Liliana Marie Prikler @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (14 more replies) 0 siblings, 15 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Hi, Here is a v2! Liliana, I tried using a function to generate the bootfile packages as you suggested, but I didn't like the result---though it is very possible I still didn't properly understand what you had in mind. I hope what I've done in this version addresses the concerns you raised about inverted inheritance and such anyway: if you'd like to compare the two, in the repository at <https://gitlab.com/philip1/guix-patches> I've tagged this series as `guix-issue-53878-v2` and the alternate as `guix-issue-53878-v2-bootfiles-proc`. I'll also include the diff below. Other than that, I hope I've addressed all your comments. > diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm > index 3e90a15d94..cbdddb1e98 100644 > --- a/gnu/packages/chez-and-racket-bootstrap.scm > +++ b/gnu/packages/chez-and-racket-bootstrap.scm > @@ -720,21 +720,18 @@ (define* (stex-make #:optional (suffix "")) > and 32-bit PowerPC architectures.") > (license license:asl2.0))) > > -(define (bootfiles-for-chez chez) > - (package/inherit chez > - (outputs '("out")) > +(define-public chez-scheme-bootstrap-bootfiles > + (package > + (inherit chez-scheme) > + (name "chez-scheme-bootstrap-bootfiles") > (inputs '()) > (native-inputs '()) > + (outputs '("out")) > (build-system copy-build-system) > ;; TODO: cross compilation > (arguments > (list #:install-plan > - #~`(("boot/" "lib/chez-scheme-bootfiles")))))) > - > -(define-public chez-scheme-bootstrap-bootfiles > - (package > - (inherit (bootfiles-for-chez chez-scheme)) > - (name "chez-scheme-bootstrap-bootfiles") > + #~`(("boot/" "lib/chez-scheme-bootfiles")))) > (supported-systems > ;; Upstream only distributes pre-built bootfiles for > ;; arm32le and t?(i3|a6)(le|nt|osx) > @@ -822,28 +819,34 @@ (define-public chez-scheme-for-racket > (license license:asl2.0))) > > (define-public chez-scheme-for-racket-bootstrap-bootfiles > - (let ((chez (bootfiles-for-chez chez-scheme-for-racket))) > - (package > - (inherit (bootfiles-for-chez chez)) > - (name "chez-scheme-for-racket-bootstrap-bootfiles") > - (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) > - (arguments > - (substitute-keyword-arguments (package-arguments chez) > - ((#:phases those-phases #~%standard-phases) > - #~(modify-phases #$those-phases > - (add-after 'unpack 'chdir > - (lambda args > - (chdir "racket/src/ChezScheme"))) > - (add-after 'chdir 'unpack-nanopass+stex > - (lambda args > - #$unpack-nanopass+stex)) > - (add-before 'install 'build > - (lambda* (#:key native-inputs inputs #:allow-other-keys) > - (invoke (search-input-file (or native-inputs inputs) > - "/opt/racket-vm/bin/racket") > - "rktboot/main.rkt"))))))) > - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") > - (description "Chez Scheme is a self-hosting compiler: building it > + (package > + (inherit chez-scheme-bootstrap-bootfiles) > + (name "chez-scheme-for-racket-bootstrap-bootfiles") > + (version (package-version chez-scheme-for-racket)) > + (source (package-source chez-scheme-for-racket)) > + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) > + (arguments > + (substitute-keyword-arguments > + (package-arguments chez-scheme-bootstrap-bootfiles) > + ((#:phases those-phases #~%standard-phases) > + #~(modify-phases #$those-phases > + (add-after 'unpack 'chdir > + (lambda args > + (chdir "racket/src/ChezScheme"))) > + (add-after 'chdir 'unpack-nanopass+stex > + (lambda args > + #$unpack-nanopass+stex)) > + (add-before 'install 'build > + (lambda* (#:key native-inputs inputs #:allow-other-keys) > + (invoke (search-input-file (or native-inputs inputs) > + "/opt/racket-vm/bin/racket") > + "rktboot/main.rkt"))))))) > + (home-page "https://github.com/racket/ChezScheme") > + ;; ^ This is downstream of https://github.com/racket/racket, > + ;; but it's designed to be a friendly landing place for people > + ;; who want a ChezScheme-shaped repositroy. > + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") > + (description "Chez Scheme is a self-hosting compiler: building it > requires ``bootfiles'' containing the Scheme-implemented portions compiled for > the current platform. (Chez can then cross-compile bootfiles for all other > supported platforms.) > @@ -857,7 +860,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles > > Note that the generated bootfiles are specific to Racket's fork of Chez > Scheme, and @code{cs-bootstrap} does not currently support building upstream > -Chez Scheme.")))) > +Chez Scheme."))) > > ;; > ;; Chez's bootstrap dependencies: -Philip Philip McGrath (15): gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: Add racket-vm-cgc. gnu: Add racket-vm-bc. gnu: Add chez-scheme-for-racket. gnu: Add racket-vm-cs. gnu: chez-mit: Support chez-scheme-for-racket. gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. gnu: racket: Update to 8.4. gnu/local.mk | 5 +- gnu/packages/chez-and-racket-bootstrap.scm | 1070 ++++++++++++ gnu/packages/chez.scm | 628 +++---- gnu/packages/emacs-xyz.scm | 4 +- gnu/packages/loko.scm | 4 +- .../racket-enable-scheme-backport.patch | 465 +++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1553 +++++++++++------ 8 files changed, 2813 insertions(+), 942 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 6:57 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (13 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. * gnu/packages/loko.scm: Likewise. * gnu/packages/racket.scm: Likewise. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 278 +++++++++++++++++++++ gnu/packages/chez.scm | 225 +---------------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- gnu/packages/racket.scm | 2 +- 6 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm diff --git a/gnu/local.mk b/gnu/local.mk index 1252643dc0..fa3a89e7a8 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -144,6 +144,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/certs.scm \ %D%/packages/check.scm \ %D%/packages/chemistry.scm \ + %D%/packages/chez-and-racket-bootstrap.scm \ %D%/packages/chez.scm \ %D%/packages/chicken.scm \ %D%/packages/chromium.scm \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm new file mode 100644 index 0000000000..f102b099fb --- /dev/null +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch> +;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> +;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> +;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages chez-and-racket-bootstrap) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix utils) + #:use-module (guix gexp) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages compression) + #:use-module (gnu packages ghostscript) + #:use-module (gnu packages linux) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages netpbm) + #:use-module (gnu packages tex) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +;; Commentary: +;; +;; Alphabetically and chronologically, Chez comes before Racket. +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Putting the relevant definitions together in this module avoids having to +;; work around dependency cycles. +;; +;; Code: + +(define nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +(define stex + ;; This commit includes a fix, which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (version "1.2.2") + (version (git-version version "1" commit))) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name "stex" version))))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version "9.5.6") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet + ;; Remove bundled libraries. + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))))))) + (build-system gnu-build-system) + (inputs + `(("libuuid" ,util-linux "lib") + ("zlib" ,zlib) + ("zlib:static" ,zlib "static") + ("lz4" ,lz4) + ("lz4:static" ,lz4 "static") + ;; for expeditor: + ("ncurses" ,ncurses) + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + ("libx11" ,libx11))) + (native-inputs + `(("nanopass" ,nanopass) ; source only + ;; for docs + ("stex" ,stex) + ("xorg-rgb" ,xorg-rgb) + ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek))) + ("ghostscript" ,ghostscript) + ("netpbm" ,netpbm))) + (native-search-paths + (list (search-path-specification + (variable "CHEZSCHEMELIBDIRS") + (files (list (string-append "lib/csv" version "-site")))))) + (outputs '("out" "doc")) + (arguments + `(#:modules + ((guix build gnu-build-system) + (guix build utils) + (ice-9 ftw) + (ice-9 match)) + #:test-target "test" + #:configure-flags + '("--threads") ;; TODO when we fix armhf, it doesn't support --threads + #:phases + (modify-phases %standard-phases + ;; put these where configure expects them to be + (add-after 'unpack 'unpack-nanopass+stex + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (for-each (lambda (dep) + (define src + (assoc-ref (or native-inputs inputs) dep)) + (copy-recursively src dep + #:keep-mtime? #t)) + '("nanopass" "stex")))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs outputs + (configure-flags '()) + #:allow-other-keys) + (let* ((zlib-static (assoc-ref inputs "zlib:static")) + (lz4-static (assoc-ref inputs "lz4:static")) + (out (assoc-ref outputs "out")) + ;; add flags which are always required: + (flags (cons* + (string-append "--installprefix=" out) + (string-append "ZLIB=" zlib-static "/lib/libz.a") + (string-append "LZ4=" lz4-static "/lib/liblz4.a") + ;; Guix will do compress man pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" ,(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke + "./configure" + flags)))) + ;; The binary file name is called "scheme" as is the one from MIT/GNU + ;; Scheme. We add a symlink to use in case both are installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bin (string-append out "/bin")) + (lib (string-append out "/lib")) + (name "chez-scheme")) + (symlink (string-append bin "/scheme") + (string-append bin "/" name)) + (map (lambda (file) + (symlink file (string-append (dirname file) + "/" name ".boot"))) + (find-files lib "scheme.boot"))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (stex-output "/tmp") + (doc-dir (string-append stex-output + "/share/doc/" + stex+version))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/" + stex+version) + (string-append "Scheme=" + (assoc-ref outputs "out") + "/bin/scheme")) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((chez+version (strip-store-file-name + (assoc-ref outputs "out"))) + (stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + (scheme (string-append (assoc-ref outputs "out") + "/bin/scheme")) + ;; see note on stex-output in phase build-stex, above: + (stexlib (string-append "/tmp" + "/lib/" + stex+version)) + (doc-dir (string-append (assoc-ref outputs "doc") + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" + "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))) + ;; Chez Scheme does not have a MIPS backend. + ;; FIXME: Debian backports patches to get armhf working. + ;; We should too. It is the Chez machine type arm32le + ;; (no threaded version upstream yet, though there is in + ;; Racket's fork), more specifically (per the release notes) ARMv6. + (supported-systems (fold delete %supported-systems + '("mips64el-linux" "armhf-linux"))) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "R6RS Scheme compiler and run-time") + (description + "Chez Scheme is a compiler and run-time system for the language of the +Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler +generates native code for each target processor, with support for x86, x86_64, +and 32-bit PowerPC architectures.") + (license license:asl2.0))) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..caf61a95f5 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -4,7 +4,6 @@ ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,234 +31,12 @@ (define-module (gnu packages chez) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (guix build-system gnu) - #:use-module (gnu packages compression) - #:use-module (gnu packages ncurses) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages ghostscript) - #:use-module (gnu packages linux) - #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) - #:use-module (gnu packages compression) - #:use-module (gnu packages image) - #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - -(define-public chez-scheme - (package - (name "chez-scheme") - (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) - (build-system gnu-build-system) - (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) - (native-search-paths - (list (search-path-specification - (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) - (outputs '("out" "doc")) - (arguments - `(#:modules - ((guix build gnu-build-system) - (guix build utils) - (ice-9 ftw) - (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) - ;; Chez Scheme does not have a MIPS backend. - ;; FIXME: Debian backports patches to get armhf working. - ;; We should too. It is the Chez machine type arm32le - ;; (no threaded version upstream yet, though there is in - ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) - (home-page "https://cisco.github.io/ChezScheme/") - (synopsis "R6RS Scheme compiler and run-time") - (description - "Chez Scheme is a compiler and run-time system for the language of the -Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler -generates native code for each target processor, with support for x86, x86_64, -and 32-bit PowerPC architectures.") - (license asl2.0))) - (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index a6e5409ff5..56697858e6 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -145,7 +145,7 @@ (define-module (gnu packages emacs-xyz) #:use-module (gnu packages aspell) #:use-module (gnu packages audio) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages cmake) #:use-module (gnu packages code) #:use-module (gnu packages cpp) diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..74a649b8a1 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -24,7 +24,7 @@ (define-module (gnu packages loko) #:use-module (gnu packages package-management) #:use-module (gnu packages guile) #:use-module (gnu packages guile-xyz) - #:use-module (gnu packages chez)) + #:use-module (gnu packages chez-and-racket-bootstrap)) (define-public loko-scheme (package diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..865fdff70f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -34,7 +34,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages compression) #:use-module (gnu packages databases) #:use-module (gnu packages fontutils) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-17 20:50 ` [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-18 6:57 ` Liliana Marie Prikler 2022-02-18 22:12 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 6:57 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... > * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. > * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. > * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. > * gnu/packages/loko.scm: Likewise. > * gnu/packages/racket.scm: Likewise. For the record, why is chez-scheme moved to bootstrap? W.r.t. the adjusted imports it might be a good idea to re-export it from chez.scm instead, but I'd need confirmation from the others on that. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-18 6:57 ` Liliana Marie Prikler @ 2022-02-18 22:12 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-18 22:12 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 3098 bytes --] Hi, On Friday, February 18, 2022 1:57:22 AM EST Liliana Marie Prikler wrote: > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... > > * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. > > * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. > > * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. > > * gnu/packages/loko.scm: Likewise. > > * gnu/packages/racket.scm: Likewise. > > For the record, why is chez-scheme moved to bootstrap? W.r.t. the > adjusted imports it might be a good idea to re-export it from chez.scm > instead, but I'd need confirmation from the others on that. Prior to this commit, there was logically a dependency cycle involving "gnu/ packages/chez.scm" and "gnu/packages/racket.scm". While it is possible, with great care, to avoid premature variable references that trigger Guile exceptions, it is easy to get wrong. At least twice Guix has ended up needing repairs, in: > commit c094e574f2b78b2f090aa740c1284418c16b2fcd > Author: raingloom <raingloom@riseup.net> > Date: Fri May 28 03:59:16 2021 +0200 > > gnu: Break up import loop between (gnu packages racket) and (gnu > packages chez). > > * gnu/packages/racket.scm: Remove (gnu packages chez) import. > > Signed-off-by: Ludovic Courtès <ludo@gnu.org> and again in: > commit 96db2ff145ecbd962206eae815b065bda7ed3d9f > Author: Ludovic Courtès <ludo@gnu.org> > Date: Tue Sep 7 15:11:46 2021 +0200 > > gnu: racket-minimal: Remove top-level reference to 'chez-scheme'. > > This could cause build errors; for instance, doing: > make && touch gnu/packages/chez.scm && make > > would trigger a "chez-scheme: unbound variable" error. > > * gnu/packages/racket.scm (racket-minimal)[source]: Add 'modules' > field. In 'snippet', remove top-level reference to CHEZ-SCHEME, which > could cause build errors. Simplify snippet. The logical cycle will only get more tangled when we can actually bootstrap Chez, as upstream Chez will then need Racket as a native input, like `chez- scheme-for-racket` does now. So, in this commit, I moved everything involved in that cycle into "chez-and- racket-bootstrap.scm". Since building the Chez Scheme and Racket compilers is almost entirely unlike building packages that use the one of the compilers, there's some logic to it organizationally, as well, but the motivation is to try to make it harder to break Guix in practice. I did try to have `(gnu packages chez)` re-export `chez-scheme`, but that caused build errors—rather illustrating the point. It does seem possible that, with the introduction of `chez-scheme-for-system`, the extra level of lambda extraction might be enough that it could be reexported from `(gnu packages chez)`. But I think it would be better for someone with a far deeper understanding of the potential pitfalls than mine to do that as a separate commit, if it seems worth doing. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (12 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". * gnu/packages/chez.scm (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez-and-racket-bootstrap.scm | 2 +- gnu/packages/chez.scm | 373 +++++++++++---------- 2 files changed, 191 insertions(+), 184 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f102b099fb..1ed4631ced 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -136,7 +136,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index caf61a95f5..54bbee7923 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -37,6 +37,28 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) + +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -54,13 +76,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -85,42 +105,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -144,95 +170,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -253,10 +258,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -284,10 +290,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -314,17 +321,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -354,10 +362,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -386,46 +395,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) (with-directory-excursion (dirname mk-file) (apply invoke "make" "build" make-flags))))) (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 03/15] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath ` (11 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez-and-racket-bootstrap (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1ed4631ced..11d570059b 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -114,9 +114,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -169,14 +167,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 6:49 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style Philip McGrath ` (10 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New private functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. --- gnu/packages/chez-and-racket-bootstrap.scm | 118 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 11d570059b..1a923fe62d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -28,7 +28,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (ice-9 match) + #:use-module (ice-9 regex) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -61,6 +63,115 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; + (define nanopass (let ((version "1.9.2")) (origin @@ -264,8 +375,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-18 6:49 ` Liliana Marie Prikler 2022-02-18 22:32 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 6:49 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine- > >nonthreaded, > chez-machine->threaded, chez-machine->nix-system, nix-system->chez- > machine, > chez-upstream-features-for-system): New private functions. > (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private > constants. > (chez-scheme)[supported-systems]: Compute based on > 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. AFAIK we don't distinguish between private/public and function (should be "procedure"), constant or variable. It's all "variable". Otherwise LGTM. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-18 6:49 ` Liliana Marie Prikler @ 2022-02-18 22:32 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-18 22:32 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 1586 bytes --] Hi, On Friday, February 18, 2022 1:49:59 AM EST Liliana Marie Prikler wrote: > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine- > > > > >nonthreaded, > > > > chez-machine->threaded, chez-machine->nix-system, nix-system->chez- > > machine, > > chez-upstream-features-for-system): New private functions. > > (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private > > constants. > > (chez-scheme)[supported-systems]: Compute based on > > 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. > > AFAIK we don't distinguish between private/public and function (should > be "procedure"), constant or variable. It's all "variable". > > > Otherwise LGTM. There are existing commits like: > commit 9e3355d2a35796276d17af13ac45814dbf6c4203 > Author: Tobias Geerinckx-Rice <me@tobias.gr> > Date: Sun Oct 3 13:50:10 2021 +0200 > > bash completion: Complete ‘guix build’ file names. > > * etc/completion/bash/guix > (_guix_complete_available_package_or_store_file): New function. > (_guix_complete): Call it in place of _guix_complete_available_package > after the ‘build’ command. and: > commit 273cf0378d6ddfcf8b882decd796ad8f9699f343 > Author: Maxim Cournoyer <maxim.cournoyer@gmail.com> > Date: Tue Jul 3 09:04:02 2018 -0400 > > gnu: Add iso-8879-entities. > > * gnu/packages/docbook.scm (iso-8879-entities): New private variable. But feel free to fix it if it's wrong! -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 7:15 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 06/15] gnu: Add stex Philip McGrath ` (9 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass, stex): Make public as a temporary workaround for Racket. * gnu/packages/racket/scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 288 ++++++++++----------- gnu/packages/racket.scm | 5 +- 2 files changed, 137 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1a923fe62d..81ac8f0774 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -172,7 +172,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -182,7 +182,7 @@ (define nanopass (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) (file-name (git-file-name "nanopass" version))))) -(define stex +(define-public stex ;; This commit includes a fix, which we would otherwise want to use as ;; patch. Let's revert to tagged releases as soon as one becomes available. (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") @@ -199,86 +199,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -286,90 +280,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 865fdff70f..a1ba57cca3 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) + ("stex" ,stex) + ("nanopass" ,nanopass))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-18 7:15 ` Liliana Marie Prikler 2022-02-18 22:43 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 7:15 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[inputs, > native-inputs]: Remove labels. > [arguments]: Use G-expressions. > <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. If nothing else is preventing you from doing so, I'd cut this patch in two here. Also > (nanopass, stex): Make public as a temporary workaround for Racket. You might want to make them public at the point of moving them to bootstrap and then hide them once you're done. If you want to prevent the user from installing them, use hidden-package instead. > * gnu/packages/racket/scm .scm > (racket-bootstrap-chez-bootfiles)[native-inputs]: > Update accordingly. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style. 2022-02-18 7:15 ` Liliana Marie Prikler @ 2022-02-18 22:43 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-18 22:43 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 1453 bytes --] Hi, On Friday, February 18, 2022 2:15:32 AM EST Liliana Marie Prikler wrote: > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[inputs, > > native-inputs]: Remove labels. > > [arguments]: Use G-expressions. > > <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. > > If nothing else is preventing you from doing so, I'd cut this patch in > two here. Also > > > (nanopass, stex): Make public as a temporary workaround for Racket. > > You might want to make them public at the point of moving them to > bootstrap and then hide them once you're done. If you want to prevent > the user from installing them, use hidden-package instead. Racket would be broken if the patch were cut in two there: it was using `assoc-ref` to extract them from the inputs of Chez, in part to work around the cyclic dependency issues, but that didn't work with the removal of input labels. In the commit that moved them to chez-and-racket-bootstrap.scm, I deliberately just cut and paste the definitions without changing anything, so I definitely wouldn't do this in that patch. Also, there was no reason to make them public until converting Chez to the new package style broke the existing workaround. > > > * gnu/packages/racket/scm > > .scm > Thanks—feel free to fix it when applying, unless a v3 ends up being needed. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 06/15] gnu: Add stex. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 07/15] gnu: Add chez-nanopass Philip McGrath ` (8 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap'. (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 215 +++++++++++++++------ gnu/packages/racket.scm | 2 +- 2 files changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 81ac8f0774..83bf15b5fb 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -31,6 +31,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -172,30 +173,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define-public stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -232,15 +209,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -263,9 +232,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -301,32 +272,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -334,7 +282,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -370,3 +320,146 @@ (define* (stex-make #:optional (suffix "")) generates native code for each target processor, with support for x86, x86_64, and 32-bit PowerPC architectures.") (license license:asl2.0))) + +;; +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license license:expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a1ba57cca3..d8338bcd6f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,7 +333,7 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,stex) + ("stex" ,(package-source stex)) ("nanopass" ,nanopass))) (arguments `(#:phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 07/15] gnu: Add chez-nanopass. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 06/15] gnu: Add stex Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (7 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex'. (chez-nanopass): New variable. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Adapt accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 96 ++++++++++++++++++---- gnu/packages/racket.scm | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 83bf15b5fb..d66955d50d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -207,9 +207,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -228,10 +226,12 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (copy-recursively + (dirname (search-input-file (or native-inputs inputs) + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) (mkdir-p "stex") (with-output-to-file "stex/Mf-stex" (lambda () @@ -454,12 +454,76 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license license:expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d8338bcd6f..e8d016c07b 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -334,7 +334,7 @@ (define-public racket-bootstrap-chez-bootfiles racket-minimal racket-minimal-bc-3m)) ("stex" ,(package-source stex)) - ("nanopass" ,nanopass))) + ("nanopass" ,(package-source chez-nanopass)))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 07/15] gnu: Add chez-nanopass Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 7:08 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc Philip McGrath ` (6 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This might seem a bit silly in isolation, but it makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. --- gnu/packages/chez-and-racket-bootstrap.scm | 51 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index d66955d50d..366815634d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -187,7 +187,7 @@ (define-public chez-scheme (sha256 (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) + (file-name (git-file-name "chez-scheme" version)) (snippet #~(begin (use-modules (guix build utils)) (for-each (lambda (dir) @@ -207,7 +207,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -237,6 +239,14 @@ (define-public chez-scheme (lambda () ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -321,6 +331,43 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license license:asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-18 7:08 ` Liliana Marie Prikler 2022-02-18 23:20 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 7:08 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > +(define-public chez-scheme-bootstrap-bootfiles > + (package > + (inherit chez-scheme) > + (name "chez-scheme-bootstrap-bootfiles") > + (inputs '()) > + (native-inputs '()) > + (outputs '("out")) > + (build-system copy-build-system) > + ;; TODO: cross compilation This TODO might be moved one line up, since you wouldn't be able to do cross-compilation with just copy-build-system, would you? > + (arguments > + (list #:install-plan > + #~`(("boot/" "lib/chez-scheme-bootfiles")))) > + (supported-systems > + ;; Upstream only distributes pre-built bootfiles for > + ;; arm32le and t?(i3|a6)(le|nt|osx) > + (filter (lambda (system) > + (let ((machine (and=> (nix-system->chez-machine > system) > + chez-machine->nonthreaded))) > + (or (equal? "arm32le" machine) > + (and machine > + (member (substring machine 0 2) '("i3" > "a6")) > + (or-map (cut string-suffix? <> machine) > + '("le" "nt" "osx")))))) > + %supported-systems)) > + (synopsis "Chez Scheme bootfiles (binary seed)") > + (description > + "Chez Scheme is a self-hosting compiler: building it requires > +``bootfiles'' containing the Scheme-implemented portions compiled > for the > +current platform. (Chez can then cross-compile bootfiles for all > other > +supported platforms.) > + > +This package provides bootstrap bootfiles for upstream Chez Scheme. > +Currently, it simply packages the binaries checked in to the upsream > +repository. Hopefully we can eventually adapt Racket's @code{cs- > bootstrap} to > +work with upstream Chez Scheme so that we can bootstrap these files > from > +source."))) > + Now to explain the difference between my suggestion and what you implemented. Mine would be to (define-public (chez-scheme-bootstrap-bootfiles chez-scheme) ...) where ... is the code you already have. This would not only work for other chez-schemes than the one we have packaged, but might also make it possible to cross module boundaries, i.e. keep chez-scheme in chez.scm. WDYT? ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-18 7:08 ` Liliana Marie Prikler @ 2022-02-18 23:20 ` Philip McGrath 2022-02-19 14:46 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-18 23:20 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 4801 bytes --] Hi, On Friday, February 18, 2022 2:08:46 AM EST Liliana Marie Prikler wrote: > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > +(define-public chez-scheme-bootstrap-bootfiles > > + (package > > + (inherit chez-scheme) > > + (name "chez-scheme-bootstrap-bootfiles") > > + (inputs '()) > > + (native-inputs '()) > > + (outputs '("out")) > > + (build-system copy-build-system) > > + ;; TODO: cross compilation > > This TODO might be moved one line up, since you wouldn't be able to do > cross-compilation with just copy-build-system, would you? > Actually, for the bootfiles, I would do cross-compilation with `copy-build- system`: the extra parts of `gnu-build-system` would just have to be deleted anyway. With the definition of `chez-scheme-for-racket-bootstrap-bootfiles` in patch v2 11/15, you could get a kind of cross compilation just by changing: (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt"))) to: (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt" "--machine" (chez-maching->threaded (chez-machine-for-system)))))) (I don't recommend that: for one thing, it would be about ten times slower than taking Chez Scheme as a native input when cross-compiling. More significantly, the harder questions about cross-compilation are in the Chez Scheme package itself, not the bootfiles. Perhaps we will end up wanting packages like `chez-scheme-bootstrap-bootfiles-ta6le` and `chez-scheme- bootstrap-bootfiles-ti3le`, analogous to e.g. `gcc-cross-sans-libc-arm-none- eabi` and `binutils-cross-x86_64-w64-mingw32`. Or maybe it will make sense to have one package build bootfiles for all supported machine types in separate outputs, and a variant of that for bootstrapping that goes through Racket for just the current machine type. Those are questions for another day.) > > + (arguments > > + (list #:install-plan > > + #~`(("boot/" "lib/chez-scheme-bootfiles")))) > > + (supported-systems > > + ;; Upstream only distributes pre-built bootfiles for > > + ;; arm32le and t?(i3|a6)(le|nt|osx) > > + (filter (lambda (system) > > + (let ((machine (and=> (nix-system->chez-machine > > system) > > + chez-machine->nonthreaded))) > > + (or (equal? "arm32le" machine) > > + (and machine > > + (member (substring machine 0 2) '("i3" > > "a6")) > > + (or-map (cut string-suffix? <> machine) > > + '("le" "nt" "osx")))))) > > + %supported-systems)) > > + (synopsis "Chez Scheme bootfiles (binary seed)") > > + (description > > + "Chez Scheme is a self-hosting compiler: building it requires > > +``bootfiles'' containing the Scheme-implemented portions compiled > > for the > > +current platform. (Chez can then cross-compile bootfiles for all > > other > > +supported platforms.) > > + > > +This package provides bootstrap bootfiles for upstream Chez Scheme. > > +Currently, it simply packages the binaries checked in to the upsream > > +repository. Hopefully we can eventually adapt Racket's @code{cs- > > bootstrap} to > > +work with upstream Chez Scheme so that we can bootstrap these files > > from > > +source."))) > > + > > Now to explain the difference between my suggestion and what you > implemented. Mine would be to > (define-public (chez-scheme-bootstrap-bootfiles chez-scheme) > ...) > where ... is the code you already have. This would not only work for > other chez-schemes than the one we have packaged, but might also make > it possible to cross module boundaries, i.e. keep chez-scheme in > chez.scm. WDYT? I still don't think I understand. How would this avoid having to override almost everything for both the upstream and Racket variants of the package, as was the case in my attempt in <https://issues.guix.gnu.org/53878#44> (also at <https://gitlab.com/philip1/guix-patches/-/blob/guix-issue-53878-v2-bootfiles-proc/gnu/packages/chez-and-racket-bootstrap.scm#L723>)? I mean, you could put the upstream stuff under the `lambda` for now, but eventually it will also need a build phase and some inputs. I just don't see what the benefit all that would achieve, or what the problem is (if there is one) with this patch. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-18 23:20 ` Philip McGrath @ 2022-02-19 14:46 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-19 14:46 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Freitag, dem 18.02.2022 um 18:20 -0500 schrieb Philip McGrath: > > Now to explain the difference between my suggestion and what you > > implemented. Mine would be to > > (define-public (chez-scheme-bootstrap-bootfiles chez-scheme) > > ...) > > where ... is the code you already have. This would not only work > > for other chez-schemes than the one we have packaged, but might > > also make it possible to cross module boundaries, i.e. keep chez- > > scheme in chez.scm. WDYT? > > I still don't think I understand. How would this avoid having to > override almost everything for both the upstream and Racket variants > of the package, as > was the case in my attempt in <https://issues.guix.gnu.org/53878#44> > (also at > < > https://gitlab.com/philip1/guix-patches/-/blob/guix-issue-53878-v2-bootfiles-proc/gnu/packages/chez-and-racket-bootstrap.scm#L723 > >)? I mean, you could put > the upstream stuff under the `lambda` for now, but eventually it will > also need a build phase and some inputs. I just don't see what the > benefit all that would achieve, or what the problem is (if there is > one) with this patch. The concern is not w.r.t variants, but version bumps, assuming that bootstrap mostly stays the same from e.g. Racket 8.4 → 8.5 (I don't have the Chez version in the back of my head atm, but you get the gist) Will be looking at v3. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 7:21 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 10/15] gnu: Add racket-vm-bc Philip McGrath ` (5 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-enable-scheme-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez-submodules, racket-vm-cgc): New variables. (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 315 +++++++++++- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ 3 files changed, 772 insertions(+), 9 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index fa3a89e7a8..aaecbc7898 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1752,6 +1752,7 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 366815634d..0dd5f4bb68 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -34,8 +34,11 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) + #:use-module (gnu packages autotools) + #:use-module (gnu packages bash) #:use-module (gnu packages compression) #:use-module (gnu packages ghostscript) + #:use-module (gnu packages libffi) #:use-module (gnu packages linux) #:use-module (gnu packages ncurses) #:use-module (gnu packages netpbm) @@ -62,6 +65,136 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; Putting the relevant definitions together in this module avoids having to ;; work around dependency cycles. ;; +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: +;; +;; - Racket BC [CGC] can be built with only a C compiler (except for +;; one caveat discussed below). +;; - Racket BC [3M] needs an existing Racket to run "xform", +;; which transforms its own C source code to add additional annotations +;; for the precise garbage collector. +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. +;; It also needs an existing Racket to compile Racket-implemented +;; parts of the runtime system to R6RS libraries. +;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate +;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler +;; purely from source into Racket and apply the compiler to itself, +;; producing the needed bootfiles (albeit very slowly). +;; Any variant of Racket since version 7.1 can run the simulation. +;; +;; So, we build CGC to build 3M to build bootfiles and CS. +;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; +;; One remaining bootstrapping limitation is that Racket's reader, module +;; system, and macro expander are implemented in Racket. For Racket CS, +;; they are compiled to R6RS libraries as discussed above. This note from the +;; README file applies to all such subsystems: +;; +;; The Racket version must be practically the same as the current Racket +;; verson, although it can be the Racket BC implementation (instead of +;; the Racket CS implementation). +;; +;; Unlike Chez Scheme boot files, the files generated in "schemified" +;; are human-readable and -editable Scheme code. That provides a way +;; out of bootstrapping black holes, even without BC. +;; +;; However, other Racket subsystems implemented in Racket for Racket CS +;; use older C implementations for Racket BC, whereas the reader, expander, +;; and module system were completely replaced with the Racket implementation +;; +;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) +;; are embeded in C as a static string constant. Eventually, they are further +;; compiled by the C-implemented Racket BC bytecode and JIT compilers. +;; (On platforms where Racket BC's JIT is not supported, yet another compiler +;; instead compiles the linklets to C code, but this is not a bootstrapping +;; issue.) +;; ;; Code: (define (chez-machine->nonthreaded machine) @@ -169,6 +302,178 @@ (define* (chez-upstream-features-for-system #:optional (else '(threads)))) +;; +;; Chez auxiliary G-expressions: +;; + +(define unbundle-chez-submodules + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) + +;; +;; Racket VM: +;; + +(define (racket-vm-common-configure-flags) + ;; under a lambda extraction to avoid evaluating bash-minimal too early + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip" + "--enable-origtree")) + +(define-public racket-vm-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-vm-cgc") + (version "8.4") + ;; ^ Remember to also update the version of + ;; chez-scheme-for-racket-bootstrap-bootfiles + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit (string-append "v" version)))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + #$unbundle-chez-submodules) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants + (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") + #:phases + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + ;; ;; Chez Scheme: ;; @@ -188,15 +493,7 @@ (define-public chez-scheme (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) (file-name (git-file-name "chez-scheme" version)) - (snippet #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib")))))) + (snippet unbundle-chez-submodules))) (build-system gnu-build-system) (inputs (list diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-18 7:21 ` Liliana Marie Prikler 2022-02-18 23:40 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 7:21 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > [...] > +(define-public racket-vm-cgc > + ;; Eventually, it may make sense for some vm packages to not be > hidden, > + ;; but this one is especially likely to remain hidden. > + (hidden-package > + (package > + (name "racket-vm-cgc") > + (version "8.4") > + ;; ^ Remember to also update the version of > + ;; chez-scheme-for-racket-bootstrap-bootfiles > + (source > + (origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/racket/racket") > + (commit (string-append "v" version)))) > + (sha256 > + (base32 > "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) > + (file-name (git-file-name "racket" version)) > + (patches (search-patches "racket-minimal-sh-via-rktio.patch" > + ;; Remove by Racket 8.5: > [...] As with the Scheme bootstrap chain, if this all depends on the same racket origin, you might want to inherit from the racket package or just (define %racket-version "8.4") (define %racket-origin (origin ...)) and use them across the packages. Making them procedures to pass version and source to would also work imo. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc. 2022-02-18 7:21 ` Liliana Marie Prikler @ 2022-02-18 23:40 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-18 23:40 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 2133 bytes --] Hi, On Friday, February 18, 2022 2:21:25 AM EST Liliana Marie Prikler wrote: > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > [...] > > +(define-public racket-vm-cgc > > + ;; Eventually, it may make sense for some vm packages to not be > > hidden, > > + ;; but this one is especially likely to remain hidden. > > + (hidden-package > > + (package > > + (name "racket-vm-cgc") > > + (version "8.4") > > + ;; ^ Remember to also update the version of > > + ;; chez-scheme-for-racket-bootstrap-bootfiles > > + (source > > + (origin > > + (method git-fetch) > > + (uri (git-reference > > + (url "https://github.com/racket/racket") > > + (commit (string-append "v" version)))) > > + (sha256 > > + (base32 > > "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) > > + (file-name (git-file-name "racket" version)) > > + (patches (search-patches "racket-minimal-sh-via-rktio.patch" > > > > + ;; Remove by Racket 8.5: > > [...] > > As with the Scheme bootstrap chain, if this all depends on the same > racket origin, you might want to inherit from the racket package or > just > (define %racket-version "8.4") > (define %racket-origin (origin ...)) > and use them across the packages. Making them procedures to pass > version and source to would also work imo. I think the `racket` package is emphatically not the right place to define the version and origin for Racket: I'll explain in more detail in reply to your comments on patch v2 15/15. I'm not opposed to `%racket-version` and `%racket-origin`—actually, I kind of like that approach. If we went that way, I'd suggest defining `%scheme-fork- version-number` (the version of `chez-scheme-for-racket`) in the same place, because it seems like it would be easy for someone to forget to update that at the same time. It should be an easy change, so I guess I'll send a v3 doing that after I reply to your other comments, rather than wait to debate it. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 10/15] gnu: Add racket-vm-bc. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 11/15] gnu: Add chez-scheme-for-racket Philip McGrath ` (4 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-bc): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 0dd5f4bb68..dc87e090cb 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -474,6 +474,29 @@ (define maybe-release-catalog ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) +(define-public racket-vm-bc + (package + (inherit racket-vm-cgc) + (name "racket-vm-bc") + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket BC [3M] implementation") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 11/15] gnu: Add chez-scheme-for-racket. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 10/15] gnu: Add racket-vm-bc Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 12/15] gnu: Add racket-vm-cs Philip McGrath ` (3 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez-and-racket-bootstrap.scm (unpack-nanopass+stex): (chez-scheme-for-racket): (chez-scheme-for-racket-bootstrap-bootfiles): New variables. (chez-scheme)[arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 131 +++++++++++++++++++-- 1 file changed, 120 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index dc87e090cb..dea49b7e89 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -317,6 +317,19 @@ (define unbundle-chez-submodules "lz4" "zlib")))) +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + ;; ;; Racket VM: ;; @@ -548,17 +561,8 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (copy-recursively - (dirname (search-input-file (or native-inputs inputs) - "lib/chez-scheme/nanopass.ss")) - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + (lambda args + #$unpack-nanopass+stex)) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (when (directory-exists? "boot") @@ -688,6 +692,111 @@ (define-public chez-scheme-bootstrap-bootfiles work with upstream Chez Scheme so that we can bootstrap these files from source."))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + (source (package-source racket-vm-cgc)) + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license license:asl2.0))) + +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (inherit chez-scheme-bootstrap-bootfiles) + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version (package-version chez-scheme-for-racket)) + (source (package-source chez-scheme-for-racket)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) + (arguments + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 12/15] gnu: Add racket-vm-cs. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (10 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 11/15] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (2 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cs): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index dea49b7e89..aa0eab4646 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -510,6 +510,50 @@ (define-public racket-vm-bc This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'')."))) + +(define-public racket-vm-cs + (package + (inherit racket-vm-bc) + (name "racket-vm-cs") + (inputs + (modify-inputs (package-inputs racket-vm-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket + chez-nanopass-bootstrap + racket-vm-bc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$unpack-nanopass+stex))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. + +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 13/15] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (11 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 12/15] gnu: Add racket-vm-cs Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4 Philip McGrath 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 54bbee7923..be251798c3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -355,7 +355,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (12 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4 Philip McGrath 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-for-system): New procedure. * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise * gnu/packages/chez.scm (chez-srfi): (chez-web): (chez-sockets): (chez-matchable): (chez-irregex): (chez-fmt): (chez-mit): (chez-scmutils): Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 14 +++++++++++++- gnu/packages/chez.scm | 16 ++++++++-------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index aa0eab4646..876c963293 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -45,7 +45,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages tex) #:use-module (gnu packages xorg) #:use-module ((guix licenses) - #:prefix license:)) + #:prefix license:) + #:export (chez-scheme-for-system)) ;; Commentary: ;; @@ -197,6 +198,17 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (and (nix-system->chez-machine system) + (not (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)))) + chez-scheme-for-racket + chez-scheme)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index be251798c3..d5007e0cfd 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -74,7 +74,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -105,7 +105,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -170,7 +170,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -256,7 +256,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -288,7 +288,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -319,7 +319,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -382,7 +382,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -413,7 +413,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 56697858e6..55f55a2f32 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index 74a649b8a1..a7ab12a0c4 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (13 preceding siblings ...) 2022-02-17 20:50 ` [bug#53878] [PATCH v2 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-17 20:50 ` Philip McGrath 2022-02-18 7:38 ` Liliana Marie Prikler 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-17 20:50 UTC (permalink / raw) To: 53878 Cc: Philip McGrath, zimoun, Ludovic Courtès, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New file. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): New procedure. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 3 +- gnu/packages/chez-and-racket-bootstrap.scm | 11 +- ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1550 +++++++++++------ 4 files changed, 1064 insertions(+), 526 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index aaecbc7898..6f4ddd3645 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1753,6 +1753,7 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 876c963293..cbdddb1e98 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages xorg) #:use-module ((guix licenses) #:prefix license:) - #:export (chez-scheme-for-system)) + #:export (chez-scheme-for-system + racket-vm-for-system)) ;; Commentary: ;; @@ -209,6 +210,14 @@ (define* (chez-scheme-for-system #:optional chez-scheme-for-racket chez-scheme)) +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..d66ff996cb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,87 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) - -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Racket -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementation -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are further -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compiler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: - -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) - -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) - + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) - (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (version (package-version (racket-vm-for-system))) + (source (package-source (racket-vm-for-system))) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs (list openssl sqlite (racket-vm-for-system))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("base") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (ice-9 match)) + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key inputs configure-flags make-flags + #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each (lambda (name) + (copy-recursively + (string-append "pkgs/" name) + (string-append #$output "/lib/racket/pkgs/" name))) + '("base" "racket-lib")))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +142,77 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (list cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:phases parent-phases #~%standard-phases) + #~(modify-phases #$parent-phases + (delete 'unpack) + (replace 'build + (lambda args + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each + (match-lambda + ((name src) + (copy-recursively + src + (string-append #$output "/lib/racket/pkgs/" name)))) + '(#$@main-distribution-packages)))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -539,82 +224,899 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs "unused-untethered-bin" "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) + +(define-public main-distribution-packages + (let* ((%racket-version (package-version (racket-vm-for-system))) + (%racket-commit (string-append "v" %racket-version))) + (append-map + (match-lambda + ((source . pkgs) + (map (match-lambda + ((? string? name) + (list name (file-append source (string-append "/" name)))) + ((name ".") + (list name source)) + ((name rel-path) + (list name (file-append source (string-append "/" rel-path))))) + pkgs))) + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,(package-source (racket-vm-for-system)) + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" "distributed-places-doc" "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" + (package-version (racket-vm-for-system))))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" "future-visualizer-pict" "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4. 2022-02-17 20:50 ` [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-18 7:38 ` Liliana Marie Prikler 2022-02-19 2:07 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-18 7:38 UTC (permalink / raw) To: Philip McGrath, 53878 Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Hi, Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > -;; Commentary: > -;; > -;; Here's how bootstrapping minimal Racket works: > -;; > -;; - Racket BC [CGC] can be built with only a C compiler (except > for > -;; one caveat discussed below). > -;; - Racket BC [3M] needs an existing Racket to run "xform", > -;; which transforms its own C source code to add additional > annotations > -;; for the precise garbage collector. > -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. > -;; It also needs an existing Racket to compile Racket- > implemented > -;; parts of the runtime system to R6RS libraries. > -;; - Chez Scheme also needs bootfiles for itself, but Racket can > simulate > -;; enough of Chez Scheme to load Racket's fork of the Chez > Scheme compiler > -;; purely from source into Racket and apply the compiler to > itself, > -;; producing the needed bootfiles (albeit very slowly). > -;; Any variant of Racket since version 7.1 can run the > simulation. > -;; > -;; So, we build CGC to build 3M to build bootfiles and CS. > -;; > -;; One remaining bootstrapping limitation is that Racket's reader, > module > -;; system, and macro expander are implemented in Racket. For Racket > CS, > -;; they are compiled to R6RS libraries as discussed above. This note > from the > -;; README file applies to all such subsystems: > -;; > -;; The Racket version must be practically the same as the > current Racket > -;; verson, although it can be the Racket BC implementation > (instead of > -;; the Racket CS implementation). > -;; > -;; Unlike Chez Scheme boot files, the files generated in > "schemified" > -;; are human-readable and -editable Scheme code. That provides a > way > -;; out of bootstrapping black holes, even without BC. > -;; > -;; However, other Racket subsystems implemented in Racket for Racket > CS > -;; use older C implementations for Racket BC, whereas the reader, > expander, > -;; and module system were completely replaced with the Racket > implementation > -;; as of Racket 7.0. > -;; > -;; For Racket BC, the compiled "linklet" s-expressions (primitive > modules) > -;; are embeded in C as a static string constant. Eventually, they > are further > -;; compiled by the C-implemented Racket BC bytecode and JIT > compilers. > -;; (On platforms where Racket BC's JIT is not supported, yet another > compiler > -;; instead compiles the linklets to C code, but this is not a > bootstrapping > -;; issue.) I think it'd be clearer if this commentary was moved along with the bootstrapping code. Is there a reason why we can't use (racket-vm-for- system) before updating Racket to 8.4? This looks like another of those "two things at once" patches. > (define-public racket-minimal > (package > (name "racket-minimal") > - (version "8.3") ; note: remember to also update > racket! > - (source > - (origin > - (method git-fetch) > - (uri (git-reference > - (url "https://github.com/racket/racket") > - (commit (string-append "v" version)))) > - (sha256 > - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") > - (file-name (git-file-name name version)) > - (patches (search-patches "racket-minimal-sh-via- > rktio.patch")) > - (modules '((guix build utils))) > - (snippet > - (with-imported-modules '((guix build utils)) > - #~(begin > - ;; Unbundle Chez submodules. > - (with-directory-excursion "racket/src/ChezScheme" > - ;; Remove bundled libraries (copied from 'chez- > scheme'). > - (for-each delete-file-recursively > - '("stex" > - "nanopass" > - "lz4" > - "zlib"))) > - ;; Unbundle libffi. > - (delete-file-recursively > "racket/src/bc/foreign/libffi")))))) > - (inputs > - `(;; common to all racket-minimal variants: > - ("openssl" ,openssl) > - ("sqlite" ,sqlite) > - ("sh" ,bash-minimal) > - ;; only for CS > - ("zlib" ,zlib) > - ("zlib:static" ,zlib "static") > - ("lz4" ,lz4) > - ("lz4:static" ,lz4 "static"))) > - (native-inputs > - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) > - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) > + (version (package-version (racket-vm-for-system))) > + (source (package-source (racket-vm-for-system))) > + ;; For cross-compilation, Matthew Flatt recommends reusing > + ;; as much of `raco cross` as possible. So, put that off until > + ;; we have a build system for Racket packages. > + (inputs (list openssl sqlite (racket-vm-for-system))) As outlined earlier, I believe Racket should define its version, not racket-vm-for-system. > [...] > (define-public racket > (package > (inherit racket-minimal) > (name "racket") > - (version (package-version racket-minimal)) ; needed for origin > uri to work > - (source > - (origin > - (method url-fetch) > - (uri (map (lambda (base) > - (string-append base version "/racket-src.tgz")) > - %installer-mirrors)) > - (sha256 > - (base32 > - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) > - (snippet > - #~(begin > - (use-modules (guix build utils) > - (ice-9 match) > - (ice-9 regex)) > - ;; unbundle minimal Racket > - (for-each delete-file-recursively > - '("collects" > - "doc" > - "etc" > - "README" > - "src")) > - ;; unbundle package sources included elsewhere > - (with-directory-excursion "share/pkgs" > - (for-each delete-file-recursively > - '#+%main-repo-main-distribution-pkgs)) > - #t)))) > + (source #f) Why? > (inputs > - `(("cairo" ,cairo) > - ("fontconfig" ,fontconfig) > - ("glib" ,glib) > - ("glu" ,glu) > - ("gmp" ,gmp) > - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg > - ("libjpeg" ,libjpeg-turbo) > - ("libpng" ,libpng) > - ("libx11" ,libx11) > - ("mesa" ,mesa) > - ("mpfr" ,mpfr) > - ("pango" ,pango) > - ("unixodbc" ,unixodbc) > - ("libedit" ,libedit))) > - (native-inputs > - `(("racket" ,racket-minimal) > - ("extend-layer" ,extend-layer) > - ("main-repo" ,(package-source racket-minimal)))) > + (list cairo > + fontconfig > + glib > + glu > + gmp > + gtk+ ;; propagates gdk-pixbuf+svg > + libjpeg-turbo > + libpng > + libx11 ;; ?? wayland ?? > + mesa > + mpfr > + pango > + unixodbc > + libedit ;; TODO reconsider in light of expeditor and > readline-gpl > + racket-minimal ;; <-- TODO non-tethered layer > + (racket-vm-for-system))) > (arguments > - `(#:phases > - (modify-phases %standard-phases > - (add-before 'configure 'unpack-packages > - (let ((unpack (assoc-ref %standard-phases 'unpack))) > - (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > - (let* ((racket (assoc-ref (or native-inputs inputs) > "racket")) > - (prefix (assoc-ref outputs "out")) > - (pkgs-dir (string-append prefix > "/share/racket/pkgs"))) > - (mkdir-p pkgs-dir) > - (copy-recursively > - "share/links.rktd" > - (string-append prefix "/share/racket/links.rktd")) > - (copy-recursively "share/pkgs" pkgs-dir) > - ;; NOTE: unpack changes the working directory > - (unpack #:source (assoc-ref (or native-inputs > inputs) > - "main-repo")) > - (for-each (lambda (pkg) > - (define dest (string-append pkgs-dir > "/" pkg)) > - (mkdir-p dest) > - (copy-recursively (string-append > "pkgs/" pkg) > - dest)) > - ',%main-repo-main-distribution-pkgs) > - #t)))) > - (replace 'configure > - (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > - (let ((racket (assoc-ref (or native-inputs inputs) > "racket")) > - (prefix (assoc-ref outputs "out"))) > - (apply invoke > - (string-append racket "/bin/racket") > - (assoc-ref inputs "extend-layer") > - racket > - prefix > - (map > - (lambda (lib) > - (string-append (assoc-ref inputs lib) > "/lib")) > - '("cairo" > - "fontconfig" > - "glib" > - "glu" > - "gmp" > - "gtk+" > - "libjpeg" > - "libpng" > - "libx11" > - "mesa" > - "mpfr" > - "pango" > - "unixodbc" > - "libedit"))) > - #t))) > - (replace 'build > - (lambda* (#:key native-inputs inputs outputs #:allow- > other-keys) > - (invoke (string-append (assoc-ref (or native-inputs > inputs) > - "racket") > - "/bin/racket") > - "--config" > - (string-append (assoc-ref outputs "out") > - "/etc/racket") > - "-l" > - "raco" > - "setup") > - #t)) > - (delete 'install)) > - ;; we still don't have these: > - #:tests? #f)) > + (substitute-keyword-arguments (package-arguments racket- > minimal) > + ((#:configure-flags _ '()) > + #~`("--tethered" > + "--extra-foreign-lib-search-dirs" > + ,(format #f "~s" > + '(#$@(map (lambda (name) > + (cond > + ((this-package-input name) > + => (cut file-append <> "/lib")) > + (else > + (raise-exception > + (make-exception > + (make-assertion-failure) > + (make-exception-with-message > + "missing input to the 'racket' > package") > + (make-exception-with-irritants > + (list name))))))) > + '("cairo" > + "fontconfig-minimal" ;; aka > fontconfig > + "glib" > + "glu" > + "gmp" > + "gtk+" > + "libjpeg-turbo" > + "libpng" > + "libx11" > + "mesa" > + "mpfr" > + "pango" > + "unixodbc" > + "libedit")))))) > + ((#:make-flags _ '()) > + #~`("main-distribution")) > + ((#:phases parent-phases #~%standard-phases) > + #~(modify-phases #$parent-phases > + (delete 'unpack) > + (replace 'build > + (lambda args > + (mkdir-p (string-append #$output > "/lib/racket/pkgs")) > + (for-each > + (match-lambda > + ((name src) > + (copy-recursively > + src > + (string-append #$output "/lib/racket/pkgs/" > name)))) > + '(#$@main-distribution-packages)))))))) > (synopsis "Programmable programming language in the Scheme > family") > (description > "Racket is a general-purpose programming language in the Scheme > family, > @@ -539,82 +224,899 @@ (define dest (string-append pkgs-dir "/" pkg)) > DrRacket IDE, libraries for GUI and web programming, and > implementations of > languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and > Datalog."))) This looks like a very weird way of phrasing union-build. Is there a reason to do this rather than union-build? Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4. 2022-02-18 7:38 ` Liliana Marie Prikler @ 2022-02-19 2:07 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 2:07 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 19196 bytes --] Hi, On Friday, February 18, 2022 2:38:52 AM EST Liliana Marie Prikler wrote: > Hi, > > Am Donnerstag, dem 17.02.2022 um 15:50 -0500 schrieb Philip McGrath: > > -;; Commentary: > > -;; > > -;; Here's how bootstrapping minimal Racket works: > > -;; > > -;; - Racket BC [CGC] can be built with only a C compiler (except > > for > > -;; one caveat discussed below). > > -;; - Racket BC [3M] needs an existing Racket to run "xform", > > -;; which transforms its own C source code to add additional > > annotations > > -;; for the precise garbage collector. > > -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. > > -;; It also needs an existing Racket to compile Racket- > > implemented > > -;; parts of the runtime system to R6RS libraries. > > -;; - Chez Scheme also needs bootfiles for itself, but Racket can > > simulate > > -;; enough of Chez Scheme to load Racket's fork of the Chez > > Scheme compiler > > -;; purely from source into Racket and apply the compiler to > > itself, > > -;; producing the needed bootfiles (albeit very slowly). > > -;; Any variant of Racket since version 7.1 can run the > > simulation. > > -;; > > -;; So, we build CGC to build 3M to build bootfiles and CS. > > -;; > > -;; One remaining bootstrapping limitation is that Racket's reader, > > module > > -;; system, and macro expander are implemented in Racket. For Racket > > CS, > > -;; they are compiled to R6RS libraries as discussed above. This note > > from the > > -;; README file applies to all such subsystems: > > -;; > > -;; The Racket version must be practically the same as the > > current Racket > > -;; verson, although it can be the Racket BC implementation > > (instead of > > -;; the Racket CS implementation). > > -;; > > -;; Unlike Chez Scheme boot files, the files generated in > > "schemified" > > -;; are human-readable and -editable Scheme code. That provides a > > way > > -;; out of bootstrapping black holes, even without BC. > > -;; > > -;; However, other Racket subsystems implemented in Racket for Racket > > CS > > -;; use older C implementations for Racket BC, whereas the reader, > > expander, > > -;; and module system were completely replaced with the Racket > > implementation > > -;; as of Racket 7.0. > > -;; > > -;; For Racket BC, the compiled "linklet" s-expressions (primitive > > modules) > > -;; are embeded in C as a static string constant. Eventually, they > > are further > > -;; compiled by the C-implemented Racket BC bytecode and JIT > > compilers. > > -;; (On platforms where Racket BC's JIT is not supported, yet another > > compiler > > -;; instead compiles the linklets to C code, but this is not a > > bootstrapping > > -;; issue.) > > I think it'd be clearer if this commentary was moved along with the > bootstrapping code. I did add it to "chez-and-racket-bootstrap.scm" at the same time as I added the Racket bootstrapping code there. But I didn't delete the bootstrapping code from this file until this commit, so I deleted the associated comment at the same time. > Is there a reason why we can't use (racket-vm-for- > system) before updating Racket to 8.4? This looks like another of > those "two things at once" patches. > The whole series based on `racket-vm-*` would not work with Racket 8.3 without backporting at least some things: off the top of my head, at a minimum, we would need b53090140596cc8522037f4c812325c71648df7a and 2b282d9c48df811cd4678cdbaed8258cdef23946 to be able to build "chez-scheme-for- racket:doc". Maybe it will seem less like "two things at once" if I explain more explicitly that "racket-minimal@8.3" is actually the same content that is now in "racket- vm-cs@8.4" (just installed into different directories), and does *not* contain anything that is now in "racket-minimal@8.4". Shortly before the release of Racket 8.3, it came to light from the intersection of a few conversations (scattered across several places, but summarised in <https://github.com/racket/racket/issues/ 3851#issuecomment-932641908> and the following two comments) that the contents of a "minimal Racket" were inconsistent. On Windows, Mac OS, and "x86_64- linux-natipkg" (a special configuration that avoids relying on a system package manager, e.g. for CI), minimal Racket had "racket-lib", "base", and packages providing native libraries (e.g. OpenSSL and SQLite). On other systems, whether using pre-built binaries or building from source using the released tarballs, "minimal Racket" would end up with only the "racket-lib" package, because "base" was pulled in only as a dependency of the native library packages. However, when building minimal Racket from the Git sources in the way Guix was, "minimal Racket" ended up with no packages installed at all. Matthew Flatt's conclusion was that, starting after the 8.3 release (to allow more time for testing), "racket-lib" should directly depend on "base", and "minimal Racket" should always explicitly install "racket-lib". (That fits the semantic roles of those packages, which represent the current always-available native libraries and the current "built in" collections in the Racket package system's model of dependencies and compatibility.) That works out especially nicely for Guix, as it gives us a clean boundary between the core Racket VM and compiler, with all of the bootstrapping involved, and building Racket packages and installation layers, which can be handled in a nice, uniform way and eventually turned into a `racket-build- system`. > > (define-public racket-minimal > > (package > > (name "racket-minimal") > > - (version "8.3") ; note: remember to also update > > racket! > > - (source > > - (origin > > - (method git-fetch) > > - (uri (git-reference > > - (url "https://github.com/racket/racket") > > - (commit (string-append "v" version)))) > > - (sha256 > > - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") > > - (file-name (git-file-name name version)) > > - (patches (search-patches "racket-minimal-sh-via- > > rktio.patch")) > > - (modules '((guix build utils))) > > - (snippet > > - (with-imported-modules '((guix build utils)) > > - #~(begin > > - ;; Unbundle Chez submodules. > > - (with-directory-excursion "racket/src/ChezScheme" > > - ;; Remove bundled libraries (copied from 'chez- > > scheme'). > > - (for-each delete-file-recursively > > - '("stex" > > - "nanopass" > > - "lz4" > > - "zlib"))) > > - ;; Unbundle libffi. > > - (delete-file-recursively > > "racket/src/bc/foreign/libffi")))))) > > - (inputs > > - `(;; common to all racket-minimal variants: > > - ("openssl" ,openssl) > > - ("sqlite" ,sqlite) > > - ("sh" ,bash-minimal) > > - ;; only for CS > > - ("zlib" ,zlib) > > - ("zlib:static" ,zlib "static") > > - ("lz4" ,lz4) > > - ("lz4:static" ,lz4 "static"))) > > - (native-inputs > > - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) > > - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) > > + (version (package-version (racket-vm-for-system))) > > + (source (package-source (racket-vm-for-system))) > > + ;; For cross-compilation, Matthew Flatt recommends reusing > > + ;; as much of `raco cross` as possible. So, put that off until > > + ;; we have a build system for Racket packages. > > + (inputs (list openssl sqlite (racket-vm-for-system))) > > As outlined earlier, I believe Racket should define its version, not > racket-vm-for-system. > As I said, I'll send a v3 with %racket-version. But the reason I think the `racket` packages would be a particularly bad place to define this for reasons related to what I was just describing. Once we have a `racket-build-system`—and we are getting ever closer—`racket-minimal` will simply be a tethered installation layer with two packages (ignoring "natipkg"), assembled with something somewhat like the `texlive-udpmap.cfg` function. The `racket` package will likewise be a tethered installation layer with 203 packages, two of which will be shared by `racket-minimal`. We will want to have others, both larger (e.g. "main-distribution-test" and all of its dependencies) and smaller (e.g. some people like just "drracket" without some of the more niche dependencies of "main-distribution", like the support libraries for the textbook, "Schreibe Dein Programm!"). A major motivation for the whole design of the Racket package system (actually, its second package system) is that the "main-distribution" package and the Racket distribution based on it should not be in any way special or built in: it happens to be released at download.racket-lang.org, but there can be many Racket distributions. Some might go so far as to argue that any special status of "main-distribution" falls under the category of weaknesses and restrictions that should be removed. > > (define-public racket > > > > (package > > (inherit racket-minimal) > > (name "racket") > > - (version (package-version racket-minimal)) ; needed for origin > > uri to work > > - (source > > - (origin > > - (method url-fetch) > > - (uri (map (lambda (base) > > - (string-append base version "/racket-src.tgz")) > > - %installer-mirrors)) > > - (sha256 > > - (base32 > > - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) > > - (snippet > > - #~(begin > > - (use-modules (guix build utils) > > - (ice-9 match) > > - (ice-9 regex)) > > - ;; unbundle minimal Racket > > - (for-each delete-file-recursively > > - '("collects" > > - "doc" > > - "etc" > > - "README" > > - "src")) > > - ;; unbundle package sources included elsewhere > > - (with-directory-excursion "share/pkgs" > > - (for-each delete-file-recursively > > - '#+%main-repo-main-distribution-pkgs)) > > - #t)))) > > + (source #f) > > Why? > The vast majority of package in `racket` are not developed in the <https:// github.com/racket/racket> repository. For that matter, the source of the "main distribution" package itself is <https://github.com/racket/main-distribution> (and, under the Racket package system's notion of versions, it is at version "0.0"). > > (inputs > > - `(("cairo" ,cairo) > > - ("fontconfig" ,fontconfig) > > - ("glib" ,glib) > > - ("glu" ,glu) > > - ("gmp" ,gmp) > > - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg > > - ("libjpeg" ,libjpeg-turbo) > > - ("libpng" ,libpng) > > - ("libx11" ,libx11) > > - ("mesa" ,mesa) > > - ("mpfr" ,mpfr) > > - ("pango" ,pango) > > - ("unixodbc" ,unixodbc) > > - ("libedit" ,libedit))) > > - (native-inputs > > - `(("racket" ,racket-minimal) > > - ("extend-layer" ,extend-layer) > > - ("main-repo" ,(package-source racket-minimal)))) > > + (list cairo > > + fontconfig > > + glib > > + glu > > + gmp > > + gtk+ ;; propagates gdk-pixbuf+svg > > + libjpeg-turbo > > + libpng > > + libx11 ;; ?? wayland ?? > > + mesa > > + mpfr > > + pango > > + unixodbc > > + libedit ;; TODO reconsider in light of expeditor and > > readline-gpl > > + racket-minimal ;; <-- TODO non-tethered layer > > + (racket-vm-for-system))) > > (arguments > > - `(#:phases > > - (modify-phases %standard-phases > > - (add-before 'configure 'unpack-packages > > - (let ((unpack (assoc-ref %standard-phases 'unpack))) > > - (lambda* (#:key native-inputs inputs outputs #:allow- > > other-keys) > > - (let* ((racket (assoc-ref (or native-inputs inputs) > > "racket")) > > - (prefix (assoc-ref outputs "out")) > > - (pkgs-dir (string-append prefix > > "/share/racket/pkgs"))) > > - (mkdir-p pkgs-dir) > > - (copy-recursively > > - "share/links.rktd" > > - (string-append prefix "/share/racket/links.rktd")) > > - (copy-recursively "share/pkgs" pkgs-dir) > > - ;; NOTE: unpack changes the working directory > > - (unpack #:source (assoc-ref (or native-inputs > > inputs) > > - "main-repo")) > > - (for-each (lambda (pkg) > > - (define dest (string-append pkgs-dir > > "/" pkg)) > > - (mkdir-p dest) > > - (copy-recursively (string-append > > "pkgs/" pkg) > > - dest)) > > - ',%main-repo-main-distribution-pkgs) > > - #t)))) > > - (replace 'configure > > - (lambda* (#:key native-inputs inputs outputs #:allow- > > other-keys) > > - (let ((racket (assoc-ref (or native-inputs inputs) > > "racket")) > > - (prefix (assoc-ref outputs "out"))) > > - (apply invoke > > - (string-append racket "/bin/racket") > > - (assoc-ref inputs "extend-layer") > > - racket > > - prefix > > - (map > > - (lambda (lib) > > - (string-append (assoc-ref inputs lib) > > "/lib")) > > - '("cairo" > > - "fontconfig" > > - "glib" > > - "glu" > > - "gmp" > > - "gtk+" > > - "libjpeg" > > - "libpng" > > - "libx11" > > - "mesa" > > - "mpfr" > > - "pango" > > - "unixodbc" > > - "libedit"))) > > - #t))) > > - (replace 'build > > - (lambda* (#:key native-inputs inputs outputs #:allow- > > other-keys) > > - (invoke (string-append (assoc-ref (or native-inputs > > inputs) > > - "racket") > > - "/bin/racket") > > - "--config" > > - (string-append (assoc-ref outputs "out") > > - "/etc/racket") > > - "-l" > > - "raco" > > - "setup") > > - #t)) > > - (delete 'install)) > > - ;; we still don't have these: > > - #:tests? #f)) > > + (substitute-keyword-arguments (package-arguments racket- > > minimal) > > + ((#:configure-flags _ '()) > > + #~`("--tethered" > > + "--extra-foreign-lib-search-dirs" > > + ,(format #f "~s" > > + '(#$@(map (lambda (name) > > + (cond > > + ((this-package-input name) > > + => (cut file-append <> "/lib")) > > + (else > > + (raise-exception > > + (make-exception > > + (make-assertion-failure) > > + (make-exception-with-message > > + "missing input to the 'racket' > > package") > > + (make-exception-with-irritants > > + (list name))))))) > > + '("cairo" > > + "fontconfig-minimal" ;; aka > > fontconfig > > + "glib" > > + "glu" > > + "gmp" > > + "gtk+" > > + "libjpeg-turbo" > > + "libpng" > > + "libx11" > > + "mesa" > > + "mpfr" > > + "pango" > > + "unixodbc" > > + "libedit")))))) > > + ((#:make-flags _ '()) > > + #~`("main-distribution")) > > + ((#:phases parent-phases #~%standard-phases) > > + #~(modify-phases #$parent-phases > > + (delete 'unpack) > > + (replace 'build > > + (lambda args > > + (mkdir-p (string-append #$output > > "/lib/racket/pkgs")) > > + (for-each > > + (match-lambda > > + ((name src) > > + (copy-recursively > > + src > > + (string-append #$output "/lib/racket/pkgs/" > > name)))) > > + '(#$@main-distribution-packages)))))))) > > (synopsis "Programmable programming language in the Scheme > > family") > > (description > > "Racket is a general-purpose programming language in the Scheme > > family, > > @@ -539,82 +224,899 @@ (define dest (string-append pkgs-dir "/" pkg)) > > DrRacket IDE, libraries for GUI and web programming, and > > implementations of > > languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and > > Datalog."))) > > This looks like a very weird way of phrasing union-build. Is there a > reason to do this rather than union-build? > IIUC, packages aren't supposed to install symbolic links into their sources, as `union-build` would do—wouldn't that prevent all of the extraneous files in those origins from being GCed? There's also the fact that `name` may be different from the name of the last element of `src`: in particular, in a significant number of cases, `src` will be something like "/gnu/store/ x22awqf0rbcyyk88kj82zihmdgkfhgza-racket-main-distribution-8.4-checkout" when `name` is "main-distribution". -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-14 15:18 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 09/11] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (2 subsequent siblings) 10 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. In the process, we also add packages for 'racket-vm-cgc', 'racket-vm-bc', and 'racket-vm-cs'. A future commit will change 'racket-minimal' to use the Racket VM implementation that best supports the target system. * gnu/packages/patches/racket-enable-scheme-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): (racket-vm-bc): (racket-vm-cs): (chez-scheme-for-racket-bootstrap-bootfiles): (chez-scheme-for-racket): New variables. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 489 +++++++++++++++++- .../racket-enable-scheme-backport.patch | 465 +++++++++++++++++ 3 files changed, 948 insertions(+), 7 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 72e086d465..8ffdd15ee2 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1787,6 +1787,7 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 38708ab690..d2f78dfae2 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -34,8 +34,11 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) + #:use-module (gnu packages autotools) + #:use-module (gnu packages bash) #:use-module (gnu packages compression) #:use-module (gnu packages ghostscript) + #:use-module (gnu packages libffi) #:use-module (gnu packages linux) #:use-module (gnu packages ncurses) #:use-module (gnu packages netpbm) @@ -62,6 +65,144 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; Putting the relevant definitions together in this module avoids having to ;; work around dependency cycles. ;; +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) One way of thinking about the +;; bounary between the Racket VM and Racket programs is that the VM implements +;; the primitives accessed by the 'ffi/unsafe/vm' library. Another perspective +;; is that DrRacket's ``Open defining file''/``Jump to definition'' features +;; can navigate into Racket programs, including into the implementation of +;; 'racket/base', but can not jump into the implementation of the Racket VM +;; itself. A third, related perspective is that Racket code is usually +;; installed with source files alongside compiled code (though this is not +;; mandatory), whereas the Racket VM is installed only in compiled form. +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: +;; +;; - Racket BC [CGC] can be built with only a C compiler (except for +;; one caveat discussed below). +;; - Racket BC [3M] needs an existing Racket to run "xform", +;; which transforms its own C source code to add additional annotations +;; for the precise garbage collector. +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. +;; It also needs an existing Racket to compile Racket-implemented +;; parts of the runtime system to R6RS libraries. +;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate +;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler +;; purely from source into Racket and apply the compiler to itself, +;; producing the needed bootfiles (albeit very slowly). +;; Any variant of Racket since version 7.1 can run the simulation. +;; +;; So, we build CGC to build 3M to build bootfiles and CS. +;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; +;; One remaining bootstrapping limitation is that Racket's reader, module +;; system, and macro expander are implemented in Racket. For Racket CS, +;; they are compiled to R6RS libraries as discussed above. This note from the +;; README file applies to all such subsystems: +;; +;; The Racket version must be practically the same as the current Racket +;; verson, although it can be the Racket BC implementation (instead of +;; the Racket CS implementation). +;; +;; Unlike Chez Scheme boot files, the files generated in "schemified" +;; are human-readable and -editable Scheme code. That provides a way +;; out of bootstrapping black holes, even without BC. +;; +;; However, other Racket subsystems implemented in Racket for Racket CS +;; use older C implementations for Racket BC, whereas the reader, expander, +;; and module system were completely replaced with the Racket implementation +;; +;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) +;; are embeded in C as a static string constant. Eventually, they are further +;; compiled by the C-implemented Racket BC bytecode and JIT compilers. +;; (On platforms where Racket BC's JIT is not supported, yet another compiler +;; instead compiles the linklets to C code, but this is not a bootstrapping +;; issue.) +;; ;; Code: (define (chez-machine->unthreaded mach) @@ -189,19 +330,19 @@ (define* (nix-system->chez-machine #:optional (system (%current-system)) (chez-machine->threaded mach))))))) ;; -;; Chez Scheme: +;; Chez auxiliary G-expressions: ;; (define unbundle-chez-submodules #~(begin (use-modules (guix build utils)) (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib")))) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) (define unpack-nanopass+stex #~(begin @@ -216,6 +357,234 @@ (define unpack-nanopass+stex ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) +;; +;; Racket VM: +;; + +(define (racket-vm-common-configure-flags) + ;; under a lambda extraction to avoid evaluating bash-minimal too early + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip" + "--enable-origtree")) + +(define-public racket-vm-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-vm-cgc") + (version "8.4") + ;; ^ Remember to also update the version of + ;; chez-scheme-for-racket-bootstrap-bootfiles + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit (string-append "v" version)))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + #$unbundle-chez-submodules) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants + (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") + #:phases + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + +(define-public racket-vm-bc + (package + (inherit racket-vm-cgc) + (name "racket-vm-bc") + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket BC [3M] implementation") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) + +(define-public racket-vm-cs + (package + (inherit racket-vm-bc) + (name "racket-vm-cs") + (inputs + (modify-inputs (package-inputs racket-vm-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket + chez-nanopass-bootstrap + racket-vm-bc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$unpack-nanopass+stex))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. + +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + +;; +;; Chez Scheme: +;; + (define-public chez-scheme-bootstrap-bootfiles (package (name "chez-scheme-bootstrap-bootfiles") @@ -401,6 +770,112 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license license:asl2.0))) + +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (inherit chez-scheme-bootstrap-bootfiles) + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + (source (package-source racket-vm-cgc)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) + (arguments + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme.") + (properties `()) + (license license:asl2.0))) + +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version (package-version chez-scheme-for-racket-bootstrap-bootfiles)) + (source (package-source racket-vm-cgc)) + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page + (package-home-page chez-scheme-for-racket-bootstrap-bootfiles)) + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license license:asl2.0))) + ;; ;; Chez's bootstrap dependencies: ;; diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket. 2022-02-13 21:51 ` [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-14 15:18 ` Liliana Marie Prikler 2022-02-16 19:58 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-14 15:18 UTC (permalink / raw) To: Philip McGrath, 53878 Hi, Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > [...] > * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): > (racket-vm-bc): > (racket-vm-cs): > (chez-scheme-for-racket-bootstrap-bootfiles): > (chez-scheme-for-racket): New variables. One patch per package is probably better. > [...] One way of thinking about the > +;; bounary between the Racket VM and Racket programs is that the VM > implements boundary. > +;; the primitives accessed by the 'ffi/unsafe/vm' library. Another > perspective > +;; is that DrRacket's ``Open defining file''/``Jump to definition'' > features > +;; can navigate into Racket programs, including into the > implementation of > +;; 'racket/base', but can not jump into the implementation of the > Racket VM > +;; itself. A third, related perspective is that Racket code is > usually > +;; installed with source files alongside compiled code (though this > is not > +;; mandatory), whereas the Racket VM is installed only in compiled > form. > [...] > +;; output. The function 'racket-vm-for-system' returns the > recomended Racket > +;; VM package for a given system. This is a very long comment. Consider how much of it is actually necessary and how much of it is not (do I really need to know about the capabilities of DrRacket for instance?) > +;; Bootstrapping Racket: > +;; --------------------- > +;; > +;; Here's how bootstrapping Racket works: > +;; > +;; - Racket BC [CGC] can be built with only a C compiler (except > for > +;; one caveat discussed below). > +;; - Racket BC [3M] needs an existing Racket to run "xform", > +;; which transforms its own C source code to add additional > annotations > +;; for the precise garbage collector. > +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. > +;; It also needs an existing Racket to compile Racket- > implemented > +;; parts of the runtime system to R6RS libraries. > +;; - Chez Scheme also needs bootfiles for itself, but Racket can > simulate > +;; enough of Chez Scheme to load Racket's fork of the Chez > Scheme compiler > +;; purely from source into Racket and apply the compiler to > itself, > +;; producing the needed bootfiles (albeit very slowly). > +;; Any variant of Racket since version 7.1 can run the > simulation. > +;; > +;; So, we build CGC to build 3M to build bootfiles and CS. This block I'd consider necessary, but again slightly on the verbose end. > +;; (Note: since the CGC variant is basically only for bootstrapping, > we > +;; often use "BC" to mean "3M", consistent with `(banner)` and the > +;; suffixes used on executables when more than one variant co- > exists.) > +;; > +;; One remaining bootstrapping limitation is that Racket's reader, > module > +;; system, and macro expander are implemented in Racket. For Racket > CS, > +;; they are compiled to R6RS libraries as discussed above. This note > from the > +;; README file applies to all such subsystems: > +;; > +;; The Racket version must be practically the same as the > current Racket > +;; verson, although it can be the Racket BC implementation > (instead of > +;; the Racket CS implementation). > +;; > +;; Unlike Chez Scheme boot files, the files generated in > "schemified" > +;; are human-readable and -editable Scheme code. That provides a > way > +;; out of bootstrapping black holes, even without BC. > +;; > +;; However, other Racket subsystems implemented in Racket for Racket > CS > +;; use older C implementations for Racket BC, whereas the reader, > expander, > +;; and module system were completely replaced with the Racket > implementation > +;; > +;; For Racket BC, the compiled "linklet" s-expressions (primitive > modules) > +;; are embeded in C as a static string constant. Eventually, they > are further > +;; compiled by the C-implemented Racket BC bytecode and JIT > compilers. > +;; (On platforms where Racket BC's JIT is not supported, yet another > compiler > +;; instead compiles the linklets to C code, but this is not a > bootstrapping > +;; issue.) > +;; Again, you want to be brief and understandable. What does this mean in practise? Do we have racket bootstrapped yet or is there still some magic hidden within? > ;; Code: > > (define (chez-machine->unthreaded mach) > @@ -189,19 +330,19 @@ (define* (nix-system->chez-machine #:optional > (system (%current-system)) > (chez-machine->threaded mach))))))) > > ;; > -;; Chez Scheme: > +;; Chez auxiliary G-expressions: > ;; > > (define unbundle-chez-submodules > #~(begin > (use-modules (guix build utils)) > (for-each (lambda (dir) > - (when (directory-exists? dir) > - (delete-file-recursively dir))) > - '("stex" > - "nanopass" > - "lz4" > - "zlib")))) > + (when (directory-exists? dir) > + (delete-file-recursively dir))) > + '("stex" > + "nanopass" > + "lz4" > + "zlib")))) As in one of your previous patches, you're mixing cosmetic changes with non-cosmetic ones. This one could be prevented by correctly indenting it in the patch that introduces it. > (define unpack-nanopass+stex > #~(begin > @@ -216,6 +357,234 @@ (define unpack-nanopass+stex > ;; otherwise, it will try to download submodules > (display "# to placate ../configure"))))) > > +;; > +;; Racket VM: > +;; > + > +(define (racket-vm-common-configure-flags) > + ;; under a lambda extraction to avoid evaluating bash-minimal too > early > + #~`(,@(cond > + ((false-if-exception > + (search-input-file %build-inputs "/bin/libtool")) > + => (lambda (libtool) > + (list (string-append "--enable-lt=" libtool)))) > + (else > + '())) > + ,@(cond > + ((false-if-exception > + (search-input-file %build-inputs "/opt/racket- > vm/bin/racket")) Did we have /opt/racket... before? We should probably avoid such paths. > + => (lambda (racket) > + (list (string-append "--enable-racket=" racket)))) > + (else > + '())) > + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" > + #$(file-append bash-minimal "/bin/sh")) > + "--disable-strip" > + "--enable-origtree") For the record, why do you need double quoting here? Would ungexp- splicing extract this too soon? > +(define-public racket-vm-cgc > + ;; Eventually, it may make sense for some vm packages to not be > hidden, > + ;; but this one is especially likely to remain hidden. > + (hidden-package > + (package > + (name "racket-vm-cgc") > + (version "8.4") > + ;; ^ Remember to also update the version of > + ;; chez-scheme-for-racket-bootstrap-bootfiles > + (source > + (origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/racket/racket") > + (commit (string-append "v" version)))) > + (sha256 > + (base32 > "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) > + (file-name (git-file-name "racket" version)) > + (patches (search-patches "racket-minimal-sh-via-rktio.patch" > + ;; Remove by Racket 8.5: > + "racket-enable-scheme- > backport.patch")) > + (modules '((guix build utils))) > + (snippet > + #~(begin > + ;; Unbundle Chez submodules. > + (with-directory-excursion "racket/src/ChezScheme" > + #$unbundle-chez-submodules) > + ;; Unbundle libffi. > + (delete-file-recursively > "racket/src/bc/foreign/libffi"))))) > + (inputs (list ncurses ;; <- common to all variants (for > #%terminal) > + bash-minimal ;; <- common to all variants (for > `system`) > + libffi)) ;; <- only for BC variants > + (native-inputs (list libtool)) ;; <- only for BC variants > + (outputs '("out" "debug")) > + (build-system gnu-build-system) > + (arguments > + (list > + #:configure-flags > + #~(cons "--enable-cgcdefault" > + #$(racket-vm-common-configure-flags)) > + ;; Tests are in packages like racket-test-core and > + ;; main-distribution-test that aren't part of the main > + ;; distribution. > + #:tests? #f > + ;; Upstream recommends #:out-of-source?, and it does > + ;; help with debugging, but it confuses `install-license- > files`. > + #:modules '((ice-9 match) > + (ice-9 regex) > + (guix build gnu-build-system) > + (guix build utils)) > + #:strip-directories #~'("opt/racket-vm/bin" > + "opt/racket-vm/lib") > + #:phases > + #~(let () > + (define* ((wrap-racket-vm-outputs phase) . args) > + (apply > + phase > + (let loop ((args args)) > + (match args > + ((#:outputs outputs . args) > + `(#:outputs > + ,(let loop ((outputs outputs)) > + (match outputs > + ((("out" . out) . outputs) > + `(("out" . ,(string-append out > "/opt/racket-vm/")) > + ,@outputs)) > + ((other . outputs) > + (cons other (loop outputs))))) > + ,@args)) > + ((arg . args) > + (cons arg (loop args))))))) Why? Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket. 2022-02-14 15:18 ` Liliana Marie Prikler @ 2022-02-16 19:58 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-16 19:58 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/14/22 10:18, Liliana Marie Prikler wrote: > Hi, > > Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >> [...] >> * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cgc): >> (racket-vm-bc): >> (racket-vm-cs): >> (chez-scheme-for-racket-bootstrap-bootfiles): >> (chez-scheme-for-racket): New variables. > One patch per package is probably better. That's fine; I'll change it. (I thought that's what I'd suggested in <https://issues.guix.gnu.org/53878#11>.) > >> [...] One way of thinking about the >> +;; bounary between the Racket VM and Racket programs is that the VM >> implements > boundary. Thanks, I'll fix it. > >> +;; the primitives accessed by the 'ffi/unsafe/vm' library. Another >> perspective >> +;; is that DrRacket's ``Open defining file''/``Jump to definition'' >> features >> +;; can navigate into Racket programs, including into the >> implementation of >> +;; 'racket/base', but can not jump into the implementation of the >> Racket VM >> +;; itself. A third, related perspective is that Racket code is >> usually >> +;; installed with source files alongside compiled code (though this >> is not >> +;; mandatory), whereas the Racket VM is installed only in compiled >> form. >> [...] >> +;; output. The function 'racket-vm-for-system' returns the >> recomended Racket >> +;; VM package for a given system. > This is a very long comment. Consider how much of it is actually > necessary and how much of it is not (do I really need to know about the > capabilities of DrRacket for instance?) I guess it would be ok to cut the explanation of the distinction between VM primitives and the ``built in'' collections, since the bottom line is that the truly primitive primitives aren't useful without the main collections. I'm not sure what else to cut that wouldn't leave room for confusion. >> +;; (Note: since the CGC variant is basically only for bootstrapping, >> we >> +;; often use "BC" to mean "3M", consistent with `(banner)` and the >> +;; suffixes used on executables when more than one variant co- >> exists.) >> +;; >> +;; One remaining bootstrapping limitation is that Racket's reader, >> module >> +;; system, and macro expander are implemented in Racket. For Racket >> CS, >> +;; they are compiled to R6RS libraries as discussed above. This note >> from the >> +;; README file applies to all such subsystems: >> +;; >> +;; The Racket version must be practically the same as the >> current Racket >> +;; verson, although it can be the Racket BC implementation >> (instead of >> +;; the Racket CS implementation). >> +;; >> +;; Unlike Chez Scheme boot files, the files generated in >> "schemified" >> +;; are human-readable and -editable Scheme code. That provides a >> way >> +;; out of bootstrapping black holes, even without BC. >> +;; >> +;; However, other Racket subsystems implemented in Racket for Racket >> CS >> +;; use older C implementations for Racket BC, whereas the reader, >> expander, >> +;; and module system were completely replaced with the Racket >> implementation >> +;; >> +;; For Racket BC, the compiled "linklet" s-expressions (primitive >> modules) >> +;; are embeded in C as a static string constant. Eventually, they >> are further >> +;; compiled by the C-implemented Racket BC bytecode and JIT >> compilers. >> +;; (On platforms where Racket BC's JIT is not supported, yet another >> compiler >> +;; instead compiles the linklets to C code, but this is not a >> bootstrapping >> +;; issue.) >> +;; > Again, you want to be brief and understandable. What does this mean in > practise? Do we have racket bootstrapped yet or is there still some > magic hidden within? This is just the comment that is currently at the top of "gnu/packages/racket.scm", but moved to this file because this is now going to be where the bootstrapping happens. Are there specific thing you want to cut? On the current state of bootstrapping, almost everything is bootstrapped from C, but the "expander" subsystem (which includes the reader and the module system) is not currently bootstrappable, though it is readily auditable. I made another attempt at an explanation in this email: https://lists.gnu.org/archive/html/guix-devel/2021-08/msg00103.html I'd welcome suggestions to improve the explanation! >> (define unbundle-chez-submodules >> #~(begin >> (use-modules (guix build utils)) >> (for-each (lambda (dir) >> - (when (directory-exists? dir) >> - (delete-file-recursively dir))) >> - '("stex" >> - "nanopass" >> - "lz4" >> - "zlib")))) >> + (when (directory-exists? dir) >> + (delete-file-recursively dir))) >> + '("stex" >> + "nanopass" >> + "lz4" >> + "zlib")))) > As in one of your previous patches, you're mixing cosmetic changes with > non-cosmetic ones. This one could be prevented by correctly indenting > it in the patch that introduces it. Sorry, I missed this in a previous round of indentation fixing. >> +;; >> +;; Racket VM: >> +;; >> + >> +(define (racket-vm-common-configure-flags) >> + ;; under a lambda extraction to avoid evaluating bash-minimal too >> early >> + #~`(,@(cond >> + ((false-if-exception >> + (search-input-file %build-inputs "/bin/libtool")) >> + => (lambda (libtool) >> + (list (string-append "--enable-lt=" libtool)))) >> + (else >> + '())) >> + ,@(cond >> + ((false-if-exception >> + (search-input-file %build-inputs "/opt/racket- >> vm/bin/racket")) > Did we have /opt/racket... before? We should probably avoid such > paths. We did not have "opt/racket-vm/" before---adding it was sort of the point of this patch series. Is the reason to avoid it a dislike for "opt", or something else? An ``in place'' build of Racket is not meant to be unpacked directly into some PREFIX where it will coexist with other software. The build is vaguely FHS-like in that e.g. it includes a "bin" directory, but it also e.g. has a "collects" directory at the top level, and it puts other things in paths like "etc/config.rktd" rather than "etc/racket/config.rktd". Subdirectories of "opt" often have that sort of layout, so it seemed like a reasonable place to put it. I considered just embracing Guix not being tied to FHS and putting it directly in the store output, but in build-side code it turned out to be useful to be able to use `search-input-{file,directory}` without potentially confusing the in-place VM with an intermediate, potentially tethered layer. If the question is, ``why do we want an in-place build?'', I can go into as much depth as you want, but it makes the build-side code easier to reason about, it's more compatible with Racket tools e.g. for cross-compilation, and it should help to reduce closure sizes by letting us build packages with non-tethered intermediate layers. >> + => (lambda (racket) >> + (list (string-append "--enable-racket=" racket)))) >> + (else >> + '())) >> + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" >> + #$(file-append bash-minimal "/bin/sh")) >> + "--disable-strip" >> + "--enable-origtree") > For the record, why do you need double quoting here? Would ungexp- > splicing extract this too soon? I'm not 100% sure I'm following your question correctly, but yes, there were problems with referencing `bash-minimal` too early. (An alternative I considered was to add these arguments in a wrapper around gnu-build-system's configure phase, so that #:configure-flags would be only for arguments that variants want to override, or plausibly might.) > >> +(define-public racket-vm-cgc >> + ;; Eventually, it may make sense for some vm packages to not be >> hidden, >> + ;; but this one is especially likely to remain hidden. >> + (hidden-package >> + (package >> + (name "racket-vm-cgc") >> + (version "8.4") >> + ;; ^ Remember to also update the version of >> + ;; chez-scheme-for-racket-bootstrap-bootfiles >> + (source >> + (origin >> + (method git-fetch) >> + (uri (git-reference >> + (url "https://github.com/racket/racket") >> + (commit (string-append "v" version)))) >> + (sha256 >> + (base32 >> "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) >> + (file-name (git-file-name "racket" version)) >> + (patches (search-patches "racket-minimal-sh-via-rktio.patch" >> + ;; Remove by Racket 8.5: >> + "racket-enable-scheme- >> backport.patch")) >> + (modules '((guix build utils))) >> + (snippet >> + #~(begin >> + ;; Unbundle Chez submodules. >> + (with-directory-excursion "racket/src/ChezScheme" >> + #$unbundle-chez-submodules) >> + ;; Unbundle libffi. >> + (delete-file-recursively >> "racket/src/bc/foreign/libffi"))))) >> + (inputs (list ncurses ;; <- common to all variants (for >> #%terminal) >> + bash-minimal ;; <- common to all variants (for >> `system`) >> + libffi)) ;; <- only for BC variants >> + (native-inputs (list libtool)) ;; <- only for BC variants >> + (outputs '("out" "debug")) >> + (build-system gnu-build-system) >> + (arguments >> + (list >> + #:configure-flags >> + #~(cons "--enable-cgcdefault" >> + #$(racket-vm-common-configure-flags)) >> + ;; Tests are in packages like racket-test-core and >> + ;; main-distribution-test that aren't part of the main >> + ;; distribution. >> + #:tests? #f >> + ;; Upstream recommends #:out-of-source?, and it does >> + ;; help with debugging, but it confuses `install-license- >> files`. >> + #:modules '((ice-9 match) >> + (ice-9 regex) >> + (guix build gnu-build-system) >> + (guix build utils)) >> + #:strip-directories #~'("opt/racket-vm/bin" >> + "opt/racket-vm/lib") >> + #:phases >> + #~(let () >> + (define* ((wrap-racket-vm-outputs phase) . args) >> + (apply >> + phase >> + (let loop ((args args)) >> + (match args >> + ((#:outputs outputs . args) >> + `(#:outputs >> + ,(let loop ((outputs outputs)) >> + (match outputs >> + ((("out" . out) . outputs) >> + `(("out" . ,(string-append out >> "/opt/racket-vm/")) >> + ,@outputs)) >> + ((other . outputs) >> + (cons other (loop outputs))))) >> + ,@args)) >> + ((arg . args) >> + (cons arg (loop args))))))) > Why? > Why what? Why 'wrap-racket-vm-outputs'? The wrapped phases don't have keywords like #:strip-directories, so adjusting their #:output argument is the only way to tell them where to find the files they need to operate on. -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 09/11] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 10/11] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4 Philip McGrath 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 54bbee7923..be251798c3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -355,7 +355,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 10/11] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 09/11] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4 Philip McGrath 10 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-for-system): New procedure. * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise * gnu/packages/chez.scm (chez-srfi): (chez-web): (chez-sockets): (chez-matchable): (chez-irregex): (chez-fmt): (chez-mit): (chez-scmutils): Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 13 ++++++++++++- gnu/packages/chez.scm | 16 ++++++++-------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index d2f78dfae2..669c54729d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -45,7 +45,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages tex) #:use-module (gnu packages xorg) #:use-module ((guix licenses) - #:prefix license:)) + #:prefix license:) + #:export (chez-scheme-for-system)) ;; Commentary: ;; @@ -205,6 +206,16 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' if it supports SYSTEM without restrictions; +'chez-scheme-racket-variant' otherwise." + (if (and=> (nix-system->chez-machine system) + chez-machine->upstream-restriction) + chez-scheme-for-racket + chez-scheme)) + (define (chez-machine->unthreaded mach) "Given a string MACH naming a Chez Scheme machine type, returns a string naming the unthreaded machine type for the same architecture and OS as MACH. diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index be251798c3..d5007e0cfd 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -74,7 +74,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -105,7 +105,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -170,7 +170,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -256,7 +256,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -288,7 +288,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -319,7 +319,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -382,7 +382,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -413,7 +413,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 02694b636a..f445ab0f25 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index 74a649b8a1..a7ab12a0c4 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4. 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-13 21:51 ` [bug#53878] [PATCH 10/11] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-13 21:51 ` Philip McGrath 2022-02-14 15:28 ` Liliana Marie Prikler 10 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-13 21:51 UTC (permalink / raw) To: 53878; +Cc: Liliana Marie Prikler, Philip McGrath * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch, gnu/packages/patcheches/racket-srfi-fsdg-backport.patch: New patches. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): New procedure. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 4 +- gnu/packages/chez-and-racket-bootstrap.scm | 11 +- ...acket-gui-tethered-launcher-backport.patch | 26 + .../patches/racket-srfi-fsdg-backport.patch | 41622 ++++++++++++++++ gnu/packages/racket.scm | 1551 +- 5 files changed, 42688 insertions(+), 526 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch create mode 100644 gnu/packages/patches/racket-srfi-fsdg-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 8ffdd15ee2..ff72ad8565 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1788,7 +1788,9 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ + %D%/packages/patches/racket-srfi-fsdg-backport.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ %D%/packages/patches/retroarch-LIBRETRO_DIRECTORY.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 669c54729d..89e659a397 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages xorg) #:use-module ((guix licenses) #:prefix license:) - #:export (chez-scheme-for-system)) + #:export (chez-scheme-for-system + racket-vm-for-system)) ;; Commentary: ;; @@ -216,6 +217,14 @@ (define* (chez-scheme-for-system #:optional chez-scheme-for-racket chez-scheme)) +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->unthreaded mach) "Given a string MACH naming a Chez Scheme machine type, returns a string naming the unthreaded machine type for the same architecture and OS as MACH. diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/patches/racket-srfi-fsdg-backport.patch b/gnu/packages/patches/racket-srfi-fsdg-backport.patch new file mode 100644 index 0000000000..75a5f46960 --- /dev/null +++ b/gnu/packages/patches/racket-srfi-fsdg-backport.patch @@ -0,0 +1,41622 @@ +From 82076308af8aeda65283ba83779302304e1a25d1 Mon Sep 17 00:00:00 2001 +From: Philip McGrath <philip@philipmcgrath.com> +Date: Thu, 20 Jan 2022 01:20:04 -0500 +Subject: [PATCH] Backport FSDG fix for Racket 8.4. + +This is a squashed and somewhat reduced version of commits +46e11b7, 48f8fca, and a2d0199. For detailed discussion, see +<https://github.com/racket/srfi/pull/15> and +<https://lists.gnu.org/archive/html/guix-devel/2022-01/msg00426.html>. +--- + srfi-doc/info.rkt | 10 +- + .../srfi/scribblings/srfi-5-doc-free.scrbl | 164 + + srfi-doc/srfi/scribblings/srfi-std/index.html | 351 +- + .../srfi/scribblings/srfi-std/racket-srfi.css | 87 + + .../srfi/scribblings/srfi-std/srfi-1.html | 2893 ++++++++++------- + .../srfi/scribblings/srfi-std/srfi-11.html | 103 +- + .../srfi/scribblings/srfi-std/srfi-13.html | 2072 +++++++----- + .../srfi/scribblings/srfi-std/srfi-14.html | 1533 +++++---- + .../srfi/scribblings/srfi-std/srfi-16.html | 101 +- + .../srfi/scribblings/srfi-std/srfi-17.html | 137 +- + .../srfi/scribblings/srfi-std/srfi-19.html | 863 ++--- + .../srfi/scribblings/srfi-std/srfi-2.html | 180 +- + .../srfi/scribblings/srfi-std/srfi-23.html | 131 +- + .../srfi/scribblings/srfi-std/srfi-25.html | 188 +- + .../srfi/scribblings/srfi-std/srfi-26.html | 408 ++- + .../srfi/scribblings/srfi-std/srfi-27.html | 695 ++-- + .../srfi/scribblings/srfi-std/srfi-28.html | 78 +- + .../srfi/scribblings/srfi-std/srfi-29.html | 88 +- + .../srfi/scribblings/srfi-std/srfi-30.html | 121 +- + .../srfi/scribblings/srfi-std/srfi-31.html | 338 +- + .../srfi/scribblings/srfi-std/srfi-34.html | 230 +- + .../srfi/scribblings/srfi-std/srfi-35.html | 222 +- + .../srfi/scribblings/srfi-std/srfi-38.html | 207 +- + .../srfi/scribblings/srfi-std/srfi-39.html | 278 +- + .../srfi/scribblings/srfi-std/srfi-4.html | 277 +- + .../srfi/scribblings/srfi-std/srfi-40.html | 232 +- + .../scribblings/srfi-std/srfi-41/srfi-41.html | 2116 ++++++------ + .../srfi/scribblings/srfi-std/srfi-42.html | 2205 +++++++------ + .../srfi/scribblings/srfi-std/srfi-43.html | 1049 +++--- + .../srfi/scribblings/srfi-std/srfi-45.html | 303 +- + .../srfi/scribblings/srfi-std/srfi-48.html | 535 +-- + .../srfi/scribblings/srfi-std/srfi-54.html | 179 +- + .../srfi/scribblings/srfi-std/srfi-57.html | 458 +-- + .../srfi/scribblings/srfi-std/srfi-59.html | 314 +- + .../srfi/scribblings/srfi-std/srfi-6.html | 156 +- + .../srfi/scribblings/srfi-std/srfi-60.html | 998 +++--- + .../srfi/scribblings/srfi-std/srfi-61.html | 64 +- + .../srfi/scribblings/srfi-std/srfi-62.html | 130 +- + .../srfi/scribblings/srfi-std/srfi-63.html | 1586 ++++----- + .../srfi/scribblings/srfi-std/srfi-64.html | 408 +-- + .../srfi/scribblings/srfi-std/srfi-66.html | 335 +- + .../srfi/scribblings/srfi-std/srfi-69.html | 346 +- + .../srfi/scribblings/srfi-std/srfi-7.html | 124 +- + .../srfi/scribblings/srfi-std/srfi-71.html | 274 +- + .../srfi/scribblings/srfi-std/srfi-74.html | 485 ++- + .../srfi/scribblings/srfi-std/srfi-78.html | 445 +-- + .../srfi/scribblings/srfi-std/srfi-8.html | 77 +- + .../srfi/scribblings/srfi-std/srfi-86.html | 202 +- + .../srfi/scribblings/srfi-std/srfi-87.html | 118 +- + .../srfi/scribblings/srfi-std/srfi-9.html | 223 +- + .../srfi/scribblings/srfi-std/srfi-98.html | 137 +- + srfi-doc/srfi/scribblings/srfi.scrbl | 70 +- + srfi-doc/srfi/scribblings/util.rkt | 17 + + srfi-lib/info.rkt | 2 + + srfi-lib/srfi/5/let.rkt | 83 +- + srfi-test/tests/srfi/5/srfi-5-test.rkt | 163 +- + srfi/info.rkt | 6 +- + 57 files changed, 14542 insertions(+), 11053 deletions(-) + create mode 100644 srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl + create mode 100644 srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css + +diff --git a/srfi-doc/info.rkt b/srfi-doc/info.rkt +index 59d9611..2ce76b3 100644 +--- a/srfi-doc/info.rkt ++++ b/srfi-doc/info.rkt +@@ -2,20 +2,18 @@ + + (define collection 'multi) + ++(define version "1.1") ++ + (define build-deps '("mzscheme-doc" + "scheme-lib" + "base" + "scribble-lib" + "srfi-lib" + "racket-doc" +- "r5rs-doc" +- "r6rs-doc" ++ "racket-index" + "compatibility-lib")) + +-(define deps '("scheme-lib" +- "base" +- "scribble-lib" +- "compatibility-lib")) ++(define deps '("base")) + + (define update-implies '("srfi-lib")) + +diff --git a/srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl b/srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl +new file mode 100644 +index 0000000..5ecf3af +--- /dev/null ++++ b/srfi-doc/srfi/scribblings/srfi-5-doc-free.scrbl +@@ -0,0 +1,164 @@ ++#lang scribble/doc ++@(require "util.rkt" ++ scribble/manual ++ scribble/example ++ scriblib/render-cond ++ scribble/core ++ scribble/html-properties ++ (for-syntax scheme/base) ++ (for-label (except-in scheme/base let) ++ srfi/5 ++ racket/stream)) ++ ++@title[#:tag "srfi-5" #:style 'unnumbered]{ ++ SRFI 5: A compatible let form with signatures and rest arguments} ++@defmodule[srfi/5] ++ ++@begin[ ++ (define-syntax-rule (defrkt rkt-let) ++ (begin ++ (require (for-label racket/base)) ++ (define rkt-let (racket let)))) ++ (defrkt rkt-let) ++ (define reference-doc ++ '(lib "scribblings/reference/reference.scrbl")) ++ (define guide-doc ++ '(lib "scribblings/guide/guide.scrbl")) ++ (define srfi-nf-doc ++ '(lib "srfi/scribblings/srfi-nf.scrbl")) ++ ] ++ ++Original specification: ++@seclink[#:indirect? #t #:doc srfi-nf-doc srfi-5-std-taglet]{SRFI 5} ++ ++For @hyperlink[srfi-license-history-url]{historical ++ reasons}, the SRFI 5 specification document has a ++@seclink[#:indirect? #t #:doc srfi-nf-doc srfi-5-license-taglet]{ ++ restrictive license} and is not included in the main Racket distribution. ++ ++The implementation in @racketmodname[srfi/5] and this ++documentation are distributed under the same ++@racket-license-link{license} as Racket: only the original ++specification document is restrictively licensed. ++ ++@defform*[[(let ([id init-expr] ...) ++ body ...+) ++ (let ([id init-expr] ...+ rest-binding) ++ body ...+) ++ (let loop-id ([id init-expr] ... maybe-rest-binding) ++ body ...+) ++ (let (loop-id [id init-expr] ... maybe-rest-binding) ++ body ...+)] ++ #:grammar ++ ([maybe-rest-binding code:blank rest-binding] ++ [rest-binding (code:line rest-id rest-init-expr ...)])]{ ++ ++ Like @rkt-let from @racketmodname[racket/base], but ++ extended to support additional variants of ++ @tech[#:doc reference-doc]{named @rkt-let}. ++ ++ As with @rkt-let from @racketmodname[racket/base], SRFI 5's ++ @racket[let] form conceptually expands to the immediate ++ application of a function to the values of the ++ @racket[init-expr]s: the @racket[id]s are bound in the ++ @racket[body]s (but not in any @racket[init-expr]s or ++ @racket[rest-init-expr]s), and @racket[loop-id], if present, ++ is bound in the @racket[body]s to the function itself, ++ allowing it to be used recursively. An @racket[id] or a ++ @racket[rest-id] can shadow @racket[loop-id], but the ++ @racket[rest-id] (if given) and all @racket[is]s much be ++ distinct. ++ ++ SRFI 5's @racket[let] adds support for a syntax like ++ @racket[define]'s @seclink[#:doc guide-doc "Function_Shorthand"]{ ++ function shorthand}, which allows the bindings to be written in a ++ syntax resembling an application of the function bound to ++ @racket[loop-id]. ++ ++ Additionally, SRFI 5's @racket[let] adds support for ++ @tech[#:doc guide-doc]{rest arguments}. If a ++ @racket[rest-id] is present, the function bound to ++ @racket[loop-id] (or the conceptual anonymous function, if ++ @racket[loop-id] is not used) will accept an unlimited ++ number of additional arguments after its required ++ by-position arguments, and the @racket[rest-id] will be ++ bound in the @racket[body]s (but not in any ++ @racket[init-expr]s or @racket[rest-init-expr]s) to a list ++ of those additional arguments. The values of the ++ @racket[rest-init-expr]s are supplied as arguments to the ++ initial, implicit application when the @racket[let] form is ++ evaluated, so the initial value bound to @racket[rest-id] is ++ @racket[(list rest-init-expr ...)]. ++ ++ @margin-note{Unlike the @racket[_kw-formals] of ++ @racket[lambda] and @racket[define] or the @racket[_formals] ++ of @racket[case-lambda], the bindings of SRFI 5's ++ @racket[let], with or without a @racket[rest-binding], are ++ always a proper (syntactic) list.} ++ ++ A @racket[rest-binding] can be used with both the ++ @racket[define]-like and the ++ @tech[#:doc reference-doc]{named-@rkt-let}--like variants of ++ @racket[let]. It is also possible to use @racket[rest-id] ++ without any @racket[loop-id]; however, as specified in the ++ grammar, at least one @racket[id]--@racket[init-expr] pair ++ is required in that case. (Otherwise, there would be an ++ ambiguity with the @racket[define]-like variant). ++ ++ @examples[ ++ #:eval (make-base-eval '(require srfi/5)) #:once ++ (code:comment "define-like bindings") ++ (define (factorial n) ++ (let (fact [n n] [acc 1]) ++ (if (zero? n) ++ acc ++ (fact (sub1 n) (* n acc))))) ++ (eval:check (factorial 5) 120) ++ (eval:check (factorial 11) 39916800) ++ (code:comment "rest arguments with named-let--like bindings") ++ (eval:check (let reverse-onto ([lst '(a b c)] ++ tail) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a)) ++ (eval:check (let reverse-onto ([lst '(a b c)] ++ tail 'x 'y 'z) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a x y z)) ++ (eval:check (let no-evens (lst 1 2 3 4 5) ++ (cond ++ [(null? lst) ++ '()] ++ [(even? (car lst)) ++ (apply no-evens (cdr lst))] ++ [else ++ (cons (car lst) (apply no-evens (cdr lst)))])) ++ '(1 3 5)) ++ (code:comment "rest arguments with define-like bindings") ++ (eval:check (let (reverse-onto [lst '(a b c)] tail) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a)) ++ (eval:check (let (reverse-onto [lst '(a b c)] . [tail 'x 'y 'z]) ++ (if (null? lst) ++ tail ++ (apply reverse-onto (cdr lst) (car lst) tail))) ++ '(c b a x y z)) ++ (eval:check (let (loop [continue? 0] args 'a 'a1 'a2) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a a1 a2) (b) (c d))) ++ (code:comment "rest arguments without any loop-id") ++ (eval:check (let ([x 1] ++ [y 2] ++ z 3 4 5 6 7) ++ (list* x y z)) ++ '(1 2 3 4 5 6 7)) ++ ] ++} +diff --git a/srfi-doc/srfi/scribblings/srfi-std/index.html b/srfi-doc/srfi/scribblings/srfi-std/index.html +index 6f03f9b..c46dd8b 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/index.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/index.html +@@ -1,258 +1,113 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +-<html> ++<!DOCTYPE html> ++<!-- ++ ++The only information that used to be in this document which isn't ++already in "../index.html" (i.e. the Scribble-generated documentation) ++is about modules which export prefixed names. That used to be ++important, before `require` was allowed to shadow bindings from a ++module's language. Is it worth incorporating this information into ++"../index.html"? ++ ++Much of this is also present in the similarly-outdated ++"srfi-lib/srfi/doc.txt". Should we do something about that, too? ++ ++???????????????????????????????????????????????????????????? ++???????????????????????????????????????????????????????????? ++???????????????????????????????????????????????????????????? ++???????????????????????????????????????????????????????????? ++ ++Certain SRFIs (currently SRFIs 1, 5, 13, 17, 19, 43, 45, 48, 61, 63, 69 and 87) provide names which conflict with names provided by the racket language. Attempting to require one of these SRFIs in a module written in the racket language will result in an error. ++ ++To address this problem, the Racket implementations of these SRFIs provide a different module which renames the problematic exports to avoid these conflicts. For SRFI 1, this library is called list, and should be required like this: ++ ++ (require srfi/1/list) ++ ++which supplies the colliding names with a prefix of 's:' (e.g. "s:map", "s:reverse!") and is therefore suitable for requires in a module. ++ ++For SRFI 19, this library is called time, and should be required like this: ++ ++ (require srfi/19/time) ++ ++which supplies the colliding names with a prefix of 'srfi:' (e.g. "srfi:date?", "srfi:date-second") and is therefore ++suitable for requires in a module. ++ ++ Supported SRFIs ++ ++SRFI File name Sub-collection ++SRFI-1 list.rkt 1 ++SRFI-2 and-let.rkt 2 ++SRFI-4(*1) 4.rkt ++SRFI-5 let.rkt 5 ++SRFI-6(+) 6.rkt ++SRFI-7 program.rkt 7 ++SRFI-8 receive.rkt 8 ++SRFI-9 record.rkt 9 ++SRFI-11(+) 11.rkt ++SRFI-13 string.rkt 13 ++SRFI-14 char-set.rkt 14 ++SRFI-16(+) 16.rkt ++SRFI-17 set.rkt 17 ++SRFI-19(*2) time.rkt 19 ++SRFI-23(+) 23.rkt ++SRFI-25 array.rkt 25 ++SRFI-26 cut.rkt 26 ++SRFI-27 random-bits.rkt 27 ++SRFI-28(+) 28.rkt ++SRFI-29 localization.rkt 29 ++SRFI-30(+) 30.rkt ++SRFI-31 rec.rkt 31 ++SRFI-32 sort.scm 32 ++SRFI-34 exception.rkt 34 ++SRFI-35 condition.rkt 35 ++SRFI-38(+) 38.rkt ++SRFI-39(+) 39.rkt ++SRFI-40 stream.rkt 40 ++SRFI-42 comprehensions.rkt 42 ++SRFI-43 vector-lib.rkt 43 ++SRFI-45(*3) lazy.rkt 45 ++SRFI-48 format.rkt 48 ++SRFI-54 cat.rkt 54 ++SRFI-57 records.rkt 57 ++SRFI-59 vicinity.rkt 59 ++SRFI-60 60.rkt 60 ++SRFI-61 cond.rkt 61 ++SRFI-62(+) ++SRFI-63 63.rkt 63 ++SRFI-64 testing.rkt 64 ++SRFI-66 66.rkt 66 ++SRFI-67 compare.rkt 67 ++SRFI-69 hash.rkt 69 ++SRFI-71 letvalues.rkt 71 ++SRFI-74 74.rkt 74 ++SRFI-78 check.rkt 78 ++SRFI-86 86.rkt 86 ++SRFI-87 case.rkt 87 ++ ++Notes: ++ +++ Supported by the Racket core ++ ++*1 The functionality is all part of racket available via (require ffi/unsafe), the only missing part is the i/o syntax. ++ ++*2 The time module does not export its time structure (you have to use the time-* procedures.) It renames all the date-* accessors to tm:date-* so that you won't get errors when including this code in other modules. Care most be taken NOT to confuse the internal date structure with the Racket one, they are not the same, and all procedures from this library expect the former. ++ ++*3 This port also provides promise? / srfi-45-promise?. ++--> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> + <title>SRFI documents inside Racket</title> ++ <meta name="viewport" content="width=device-width, initial-scale=1" /> ++ <meta http-equiv="refresh" content="5;url=../index.html" /> + </head> +- + <body> + <h1>SRFI documents inside Racket</h1> +- +- <h1>Scheme Requests for Implementation</h1> +- +- <p>The "Scheme Requests for Implementation" (<em>SRFI</em>) process +- is a new approach to helping Scheme users to write portable and +- yet useful code. It is a forum for people interested in +- coordinating libraries and other additions to the Scheme language +- between implementations.</p> +- +- <p>This manual includes the <em style="font-style: normal">original</em> documentation of all +- the SRFIs already ported to Racket. For more information on +- the SRFI process, please <a href="http://srfi.schemers.org">follow +- this link</a>.</p> +- +- +- <h2>Loading</h2> +- +- <p>To load a SRFI with name conflicts (currently SRFIs 1, 5, 13, 17, 19, 43, +- 45, 48, 61, 63, 69 and 87) in a module,<br> +- please see the note below.<br> +- <br> +- To load a SRFI, use the following form:<br> +- <br> +- (require srfi/N)<br> +- <br> +- if you know the number of the SRFI you want to load. This is the preferred +- method. Alternatively, use this one:<br> +- <br> +- (require srfi/N/NAME)<br> +- <br> +- if you know the `informative name' of the SRFI.<br> +- <br> +- N, is a number corresponding to the sub-collection that holds a particular +- SRFI, and NAME is a more descriptive name we assigned to the main file in +- which the SRFI is defined. For instance, to load SRFI-34 you have to do +- either one of:<br> +- <br> +- (require srfi/34)<br> +- <br> +- or,<br> +- <br> +- (require srfi/34/exception)<br> +- <br> +- </p> +- +- + <p> +- <b><font color="#FF0000">NOTE on SRFIs with name conflicts</font><br> +- </b><br> +- Certain SRFIs (currently SRFIs 1, 5, 13, 17, 19, 43, 45, 48, 61, 63, 69 and +- 87) provide names which conflict with names provided by the <tt>racket</tt> +- language. Attempting to require one of these SRFIs in a module written in +- the <tt>racket</tt> language will result in an error.<br> +- <br> +- To address this problem, the Racket implementations of these SRFIs provide a +- different module which renames the problematic exports to avoid these +- conflicts. For SRFI 1, this library is called list, and should be +- required like this:<br> +- <br> +- (require srfi/1/list)<br> +- <br> +- which supplies the colliding names with a prefix of 's:' (e.g. "s:map", +- "s:reverse!") and is therefore suitable for requires in a module.<br> +- <br> +- For SRFI 19, this library is called time, and should be required like +- this:<br> +- <br> +- (require srfi/19/time)<br> +- <br> +- which supplies the colliding names with a prefix of 'srfi:' (e.g. +- "srfi:date?", "srfi:date-second") and is therefore<br> +- suitable for requires in a module.<br> +- <br> ++ The information that used to be on this page has moved to ++ <a href="../index.html">../index.html</a>. + </p> +- +- + <p> +- <b>Supported SRFIs</b><br> ++ If you do nothing, you should be redirected in five seconds. + </p> +- +- +- <p>SRFI File +- name +- Sub-collection<br> +- SRFI-1 list.rkt +- 1<br> +- SRFI-2 and-let.rkt +- 2<br> +- SRFI-4(*1) 4.rkt<br> +- SRFI-5 let.rkt +- 5<br> +- SRFI-6(+) 6.rkt<br> +- SRFI-7 program.rkt +- 7<br> +- SRFI-8 receive.rkt +- 8<br> +- SRFI-9 record.rkt +- 9<br> +- SRFI-11(+) 11.rkt<br> +- SRFI-13 string.rkt +- 13<br> +- SRFI-14 char-set.rkt +- 14<br> +- SRFI-16(+) 16.rkt<br> +- SRFI-17 set.rkt +- 17<br> +- SRFI-19(*2) time.rkt +- 19<br> +- SRFI-23(+) 23.rkt<br> +- SRFI-25 array.rkt +- 25<br> +- SRFI-26 cut.rkt +- 26<br> +- SRFI-27 random-bits.rkt +- 27<br> +- SRFI-28(+) 28.rkt<br> +- SRFI-29 localization.rkt +- 29<br> +- SRFI-30(+) 30.rkt<br> +- SRFI-31 rec.rkt +- 31<br> +- SRFI-32 sort.scm +- 32<br> +- SRFI-34 exception.rkt +- 34<br> +- SRFI-35 condition.rkt +- 35<br> +- SRFI-38(+) 38.rkt<br> +- SRFI-39(+) 39.rkt<br> +- SRFI-40 stream.rkt +- 40<br> +- SRFI-42 comprehensions.rkt +- 42<br> +- SRFI-43 vector-lib.rkt +- 43<br> +- SRFI-45(*3) lazy.rkt +- 45<br> +- SRFI-48 format.rkt +- 48<br> +- SRFI-54 cat.rkt +- 54<br> +- SRFI-57 records.rkt +- 57<br> +- SRFI-59 vicinity.rkt +- 59<br> +- SRFI-60 60.rkt +- 60<br> +- SRFI-61 cond.rkt +- 61<br> +- SRFI-62(+)<br> +- SRFI-63 63.rkt +- 63<br> +- SRFI-64 testing.rkt +- 64<br> +- SRFI-66 66.rkt +- 66<br> +- SRFI-67 compare.rkt +- 67<br> +- SRFI-69 hash.rkt +- 69<br> +- SRFI-71 letvalues.rkt +- 71<br> +- SRFI-74 74.rkt +- 74<br> +- SRFI-78 check.rkt +- 78<br> +- SRFI-86 86.rkt +- 86<br> +- SRFI-87 case.rkt +- 87<br> +- </p> +- +- +- <p><b>Notes:</b></p> +- +- +- <p>+ Supported by the Racket core<br> +- <br> +- *1 The functionality is all part of racket available +- via (require ffi/unsafe), the only missing part is the i/o +- syntax.<br> +- <br> +- *2 The time module does not export its time structure +- (you have to use the time-* procedures.) It renames all +- the date-* accessors to tm:date-* so that you won't get +- errors when including this code in other modules. Care +- most be taken NOT to confuse the internal date structure +- with the Racket one, they are not the same, and all +- procedures from this library expect the former.<br> +- <br> +- *3 This port also provides promise? / srfi-45-promise?.<br> +- </p> +- +- +- <h2>Ported SRFIs: original documents</h2> +- +- <ul> +- <li><a href="srfi-1.html">SRFI 1: List Library</a></li> +- <li><a href="srfi-2.html">SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* special form</a></li> +- <li><a href="srfi-4.html">SRFI 4: Homogeneous numeric vector datatypes</a></li> +- <li><a href="srfi-5.html">SRFI 5: A compatible let form with signatures and rest arguments</a></li> +- <li><a href="srfi-6.html">SRFI 6: Basic String Ports</a></li> +- <li><a href="srfi-7.html">SRFI 7: Feature-based program configuration language</a></li> +- <li><a href="srfi-8.html">SRFI 8: RECEIVE: Binding to multiple values</a></li> +- <li><a href="srfi-9.html">SRFI 9: Defining Record Types</a></li> +- <li><a href="srfi-11.html">SRFI 11: Syntax for receiving multiple values</a></li> +- <li><a href="srfi-13.html">SRFI 13: String Libraries</a></li> +- <li><a href="srfi-14.html">SRFI 14: Character-set Library</a></li> +- <li><a href="srfi-16.html">SRFI 16: Syntax for procedures of variable arity</a></li> +- <li><a href="srfi-17.html">SRFI 17: Generalized set!</a></li> +- <!-- SRFI 18 is partially supported. I'm not moving the document so as not to give false hopes! --> +- <li><a href="srfi-19.html">SRFI 19: Time Data Types and Procedures</a></li> +- <li><a href="srfi-23.html">SRFI 23: Error reporting mechanism</a></li> +- <li><a href="srfi-25.html">SRFI 25: Multi-dimensional Array Primitives</a></li> +- <li><a href="srfi-26.html">SRFI 26: Notation for Specializing Parameters without Currying</a></li> +- <li><a href="srfi-27.html">SRFI 27: Sources of Random Bits</a></li> +- <li><a href="srfi-28.html">SRFI 28: Basic Format Strings</a></li> +- <li><a href="srfi-29.html">SRFI 29: Localization</a></li> +- <li><a href="srfi-30.html">SRFI 30: Nested Multi-line Comments</a></li> +- <li><a href="srfi-31.html">SRFI 31: A special form rec for recursive evaluation</a></li> +- <li><a href="srfi-34.html">SRFI 34: Exception Handling for Programs</a></li> +- <li><a href="srfi-35.html">SRFI 35: Conditions</a></li> +- <li><a href="srfi-38.html">SRFI 38: External Representation for Data With Shared Structure</a></li> +- <li><a href="srfi-39.html">SRFI 39: Parameter objects</a></li> +- <li><a href="srfi-40.html">SRFI 40: A Library of Streams</a></li> +- <li><a href="srfi-42.html">SRFI 42: Eager Comprehensions</a></li> +- <li><a href="srfi-43.html">SRFI 43: Vector Library</a></li> +- <li><a href="srfi-45.html">SRFI 45: Primitives for Expressing Iterative Lazy Algorithms</a></li> +- <li><a href="srfi-48.html">SRFI 48: Intermediate Format Strings</a></li> +- <li><a href="srfi-54.html">SRFI 54: Formatting</a></li> +- <li><a href="srfi-57.html">SRFI 57: Records</a></li> +- <li><a href="srfi-59.html">SRFI 59: Vicinity</a></li> +- <li><a href="srfi-60.html">SRFI 60: Integers as Bits</a></li> +- <li><a href="srfi-61.html">SRFI 61: A more general cond clause</a></li> +- <li><a href="srfi-62.html">SRFI 62: S-expression comments</a></li> +- <li><a href="srfi-63.html">SRFI 63: Homogeneous and Heterogeneous Arrays</a></li> +- <li><a href="srfi-64.html">SRFI 64: A Scheme API for test suites</a></li> +- <li><a href="srfi-66.html">SRFI 66: Octet Vectors</a></li> +- <li><a href="srfi-67/srfi-67.html">SRFI 67: Compare Procedures</a></li> +- <li><a href="srfi-69.html">SRFI 69: Basic hash tables</a></li> +- <li><a href="srfi-71.html">SRFI 71: Extended LET-syntax for multiple values</a></li> +- <li><a href="srfi-74.html">SRFI 74: Octet-Addressed Binary Blocks</a></li> +- <li><a href="srfi-78.html">SRFI 78: Lightweight testing</a></li> +- <li><a href="srfi-86.html">SRFI 86: MU and NU simulating VALUES & +- CALL-WITH-VALUES, and their related LET-syntax</a></li> +- <li><a href="srfi-87.html">SRFI 87: => in case clauses</a></li> +- </ul> +- +- </body> ++ </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css b/srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css +new file mode 100644 +index 0000000..661e2cb +--- /dev/null ++++ b/srfi-doc/srfi/scribblings/srfi-std/racket-srfi.css +@@ -0,0 +1,87 @@ ++/* ++ This is a substitute for "srfi.css" from ++ https://github.com/scheme-requests-for-implementation/srfi-common ++*/ ++@import "../../scribble.css"; ++@import "../../manual-style.css"; ++@import "../../manual-racket.css"; ++/* NB doc-site.css is imported at the end of this file */ ++ ++a.eponymous { ++ /* based on upstream srfi.css */ ++ font-family: 'Fira-Mono', monospace; ++ overflow-wrap: break-word; ++ word-break: break-all; ++ word-wrap: break-word; ++} ++body > p:first-of-type { ++ /* this is the SRFI author */ ++ font-family: 'Fira', sans-serif; ++ font-size: 1.3em; ++} ++body { ++ /* like .maincolumn from manual-style.css */ ++ width: auto; ++ margin-top: 4rem; ++ margin-left: 17rem; ++ margin-right: 2rem; ++ margin-bottom: 10rem; /* to avoid fixed bottom nav bar */ ++ max-width: 700px; ++ min-width: 370px; /* below this size, code samples don't fit */ ++} ++@media (max-width:720px) { ++ /* adapt to narrow screens, like .maincolumn in manual-style.css */ ++ body { ++ margin-left: 1em; ++ margin-top: 7rem; ++ margin-bottom: 0rem; ++ } ++} ++.refpara.racket-srfi-note .refcolumn { ++ /* Overrides @media rule to put .refcolumn in the margin on wide ++ screens. This is necessary because some SRFIs (e.g. 14) include ++ inline stylesheets that interfere with the way it tries to use ++ `float`. ++ */ ++ margin: inherit; ++ float: inherit; ++ clear: inherit; ++ width: inherit; ++} ++h1 { ++ /* like h2 from manual-style.css */ ++ font-family: 'Cooper-Hewitt'; ++ font-size: 2.3rem; ++ font-weight: bold; ++ line-height: 1.2; ++ width: 90%; ++} ++h2 { ++ /* like h3 -- h8 in manual-style.css */ ++ margin-top: 2em; ++ padding-top: 0.1em; ++ margin-bottom: 0.75em; ++ font-size: 2rem; ++} ++h3, h4, h5, h6, h7, h8 { ++ border: none; ++} ++span.antispam { ++ display: none; ++} ++pre, dl, dd, ol, ul { ++ /* like p from manual-style.css */ ++ margin-bottom: 1em; ++} ++li { ++ /* slightly tighter than p */ ++ margin-bottom: 0.6em; ++} ++.srfi-plt-extension { ++ /* like the background color for .boxed (blue boxes), ++ but without the gradient */ ++ background-color: hsl(216, 78%, 95%); ++} ++ ++/* Goes last, so it can override everything. */ ++@import "../../doc-site.css"; +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html +index 773c03b..f1ccc40 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-1.html +@@ -1,24 +1,41 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" +- 'http://www.w3.org/TR/REC-html40/strict.dtd'> +- ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> ++<html lang="en-US"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-1 ┃ ++┃ Commit: 27c2652bae97e632029b24784dab1181ffbcd7c5 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <!-- Is there a portable way to write an em-dash? + Can I have bangs, plusses, or slashes in #tags? Spaces? + Yes: plus, bang, star No: space Yes: slash, question, ampersand + You can't put sharp in a path, so anything goes, really. + Nonetheless, some of these confuse Netscape, so I'll avoid them. + --> +- + <!--========================================================================--> +-<html lang=en-US> +- <head> +- <meta name="keywords" content="Scheme, programming language, list processing, SRFI, youthful devotees of intra-gender communion"> +- <link rev=made href="mailto:shivers@ai.mit.edu"> ++ <meta content="Scheme, programming language, list processing, SRFI" name="keywords" /> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + <title>SRFI 1: List Library</title> + + <!-- Should have a media=all to get, for example, printing to work. + == But my Netscape will completely ignore the tag if I do that. + --> + <style type="text/css"> ++ /*<![CDATA[*/ + /* A little general layout hackery for headers & the title. */ + body { margin-left: +7%; + font-family: "Helvetica", sans-serif; +@@ -46,7 +63,7 @@ + ** sheets and dl list rendering. We have to set truly random + ** values here to get the rendering to come out. The proper values + ** are in the following style sheet, for Internet Explorer. +- ** In the following settings, the *comments* say what the ++ ** In the following settings, the *comments* say what the + ** setting *really* causes Netscape to do. + ** + ** Ugh. Professional coders sacrifice their self-respect, +@@ -63,17 +80,17 @@ + dt.proc-def { margin-top: 0ex; margin-bottom: 3ex; } + + /* m-b sets space between dd & dt; m-t ignored. */ +- dd.proc-def { margin-bottom: 0.5ex; margin-top: 0ex; } ++ dd.proc-def { margin-bottom: 0.5ex; margin-top: 0ex; } + + + /* Boldface the name of a procedure when it's being defined. */ + code.proc-def { font-weight: bold; font-size: 110%} + +- /* For the index of procedures. ++ /* For the index of procedures. + ** Same hackery as for dt.proc-def, above. + */ + /* m-b sets space between dd & dt; m-t ignored. */ +- dd.proc-index { margin-bottom: 0ex; margin-top: 0ex; } ++ dd.proc-index { margin-bottom: 0ex; margin-top: 0ex; } + /* What the fuck? */ + pre.proc-index { margin-top: -2ex; } + +@@ -82,7 +99,7 @@ + */ + #toc-table { margin-top: -2ex; margin-left: -5%; } + +- /* R5RS proc names are in italic; extended R5RS names ++ /* R5RS proc names are in italic; extended R5RS names + ** in italic boldface. + */ + span.r5rs-proc { font-weight: bold; } +@@ -95,13 +112,15 @@ + dt.biblio { margin-bottom: 1ex; } + + /* Links to draft copies (e.g., not at the official SRFI site) +- ** are colored in red, so people will use them during the ++ ** are colored in red, so people will use them during the + ** development process and kill them when the document's done. + */ + a.draft { color: red; } ++ /*]]>*/ + </style> + +- <style type="text/css"; media=all> ++ <style media="all" type="text/css"> ++ /*<![CDATA[*/ + /* Nastiness: Here, I'm using a bug to work around a bug. + ** Netscape rendering bugs mean you need bogus <dt> and <dd> + ** margin settings -- settings which screw up IE's proper rendering. +@@ -117,102 +136,108 @@ + + pre { margin-top: 1ex; } + +- dd.proc-def { margin-bottom: 2ex; margin-top: 0.5ex; } ++ dd.proc-def { margin-bottom: 2ex; margin-top: 0.5ex; } + +- /* For the index of procedures. ++ /* For the index of procedures. + ** Same hackery as for dt.proc-def, above. + */ +- dd.proc-index { margin-top: 0ex; } ++ dd.proc-index { margin-top: 0ex; } + pre.proc-index { margin-top: 0ex; } + + /* Spread out bibliographic lists. */ + dt.biblio { margin-top: 3ex; margin-bottom: 0ex; } + dd.biblio { margin-bottom: 1ex; } ++ /*]]>*/ + </style> + </head> + + <body> + + <!--========================================================================--> +-<H1>Title</H1><div class=title-text> +-SRFI-1: List Library +-</div> +- +-<!--========================================================================--> +-<H1>Author</H1> ++<h1>SRFI 1: List Library</h1> + +-Olin Shivers +- +- <address> +- <a href="http://www.ai.mit.edu/~shivers/">http://www.ai.mit.edu/~shivers/</A> / +- <a href="mailto:shivers@ai.mit.edu">shivers@ai.mit.edu</A> +- </address> ++<p>by Olin Shivers</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 1 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-1/srfi-1.html">https://srfi.schemers.org/srfi-1/srfi-1.html</a>.</p></blockquote></blockquote></blockquote> + + <!--========================================================================--> +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-1/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P> +-<UL> +- <LI>Received: 1998/11/08</LI> +- <LI>Draft: 1998/12/22-1999/03/09</LI> +- <LI>Revised: several times</LI> +- <LI>Final: 1999/10/09</LI> +-</UL> ++<h2 id="status">Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+1%20%20+at+srfi+dotschemers+dot+org">srfi-1 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-1">archive</a>.</p> ++<ul> ++ <li>Received: 1998-11-08</li> ++ <li>Draft: 1998-12-22--1999-03-09</li> ++ <li>Revised: several times</li> ++ <li>Final: 1999-10-09</li> ++ <li>Revised to fix errata: ++ <ul> ++ <li>2016-08-27 (Clarify Booleans.)</li> ++ <li>2018-10-08 (Remove extra parenthesis.)</li> ++ <li>2019-10-25 (Fix broken links.)</li> ++ <li>2020-06-02 (Add <a href="#lset%3D-element-equality-order">note</a> ++ about order of arguments to <code>lset=</code>.)</li> ++ </ul> ++ </li> ++</ul> + + <!--========================================================================--> +-<h1>Table of contents</H1> ++<h2>Table of contents</h2> + + <!-- A bug in netscape (?) keeps the first link in this UL from being active. + ==== So the Abstract link be dead. 99/8/22 -Olin + --> +-<ul id=toc-table> +-<li><a href="#Abstract">Abstract</a> +-<li><a href="#Rationale">Rationale</a> +-<li><a href="#ProcedureIndex">Procedure index</a> +-<li><a href="#GeneralDiscussion">General discussion</a> +- <ul> +- <li><a href="#LinearUpdateProcedures">"Linear update" procedures</a> +- <li><a href="#ImproperLists">Improper lists</a> +- <li><a href="#Errors">Errors</a> +- <li><a href="#NotIncludedInThisLibrary">Not included in this library</a> +- </ul> +-<li><a href="#TheProcedures">The procedures</a> +- <ul> +- <li><a href="#Constructors">Constructors</a> +- <li><a href="#Predicates">Predicates</a> +- <li><a href="#Selectors">Selectors</a> +- <li><a href="#Miscellaneous">Miscellaneous: length, append, reverse, zip & count</a> +- <li><a href="#FoldUnfoldMap">Fold, unfold, and map</a> +- <li><a href="#FilteringPartitioning">Filtering & partitioning</a> +- <li><a href="#Searching">Searching</a> +- <li><a href="#Deletion">Deletion</a> +- <li><a href="#AssociationLists">Association lists</a> +- <li><a href="#SetOperationsOnLists">Set operations on lists</a> +- <li><a href="#PrimitiveSideEffects">Primitive side-effects</a> +- </ul> +-<li><a href="#Acknowledgements">Acknowledgements</a> +-<li><a href="#ReferencesLinks">References & links</a> +-<li><a href="#Copyright">Copyright</a> ++<ul id="toc-table"> ++ <li><a href="#Abstract">Abstract</a></li> ++ <li><a href="#Rationale">Rationale</a></li> ++ <li><a href="#ProcedureIndex">Procedure index</a></li> ++ <li> ++ <a href="#GeneralDiscussion">General discussion</a> ++ <ul> ++ <li><a href="#LinearUpdateProcedures">"Linear update" procedures</a></li> ++ <li><a href="#ImproperLists">Improper lists</a></li> ++ <li><a href="#Errors">Errors</a></li> ++ <li><a href="#NotIncludedInThisLibrary">Not included in this library</a></li> ++ </ul> ++ </li> ++ <li> ++ <a href="#TheProcedures">The procedures</a> ++ <ul> ++ <li><a href="#Constructors">Constructors</a></li> ++ <li><a href="#Predicates">Predicates</a></li> ++ <li><a href="#Selectors">Selectors</a></li> ++ <li><a href="#Miscellaneous">Miscellaneous: length, append, reverse, zip & count</a></li> ++ <li><a href="#FoldUnfoldMap">Fold, unfold, and map</a></li> ++ <li><a href="#FilteringPartitioning">Filtering & partitioning</a></li> ++ <li><a href="#Searching">Searching</a></li><li><a href="#Deletion">Deletion</a></li> ++ <li><a href="#AssociationLists">Association lists</a></li> ++ <li><a href="#SetOperationsOnLists">Set operations on lists</a></li> ++ <li><a href="#PrimitiveSideEffects">Primitive side-effects</a></li> ++ </ul> ++ </li> ++ <li><a href="#Acknowledgements">Acknowledgements</a></li> ++ <li><a href="#ReferencesLinks">References & links</a></li> ++ <li><a href="#Copyright">Copyright</a></li> + </ul> + + + <!--========================================================================--> +-<h1><a name="Abstract">Abstract</a></H1> ++<h2 id="Abstract">Abstract</h2> + <p> + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> Scheme has an impoverished set of list-processing utilities, which is a + problem for authors of portable code. This <abbr title="Scheme Request for Implementation">SRFI</abbr> proposes a coherent and + comprehensive set of list-processing procedures; it is accompanied by a + reference implementation of the spec. The reference implementation is ++</p> + <ul> +-<li>portable +-<li>efficient +-<li>completely open, public-domain source ++ <li>portable</li> ++ <li>efficient</li> ++ <li>completely open, public-domain source</li> + </ul> + + <!--========================================================================--> +-<h1><a name="Rationale">Rationale</a></h1> ++<h2 id="Rationale">Rationale</h2> + <p> + The set of basic list and pair operations provided by R4RS/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> Scheme is far + from satisfactory. Because this set is so small and basic, most +@@ -220,7 +245,7 @@ implementations provide additional utilities, such as a list-filtering + function, or a "left fold" operator, and so forth. But, of course, this + introduces incompatibilities -- different Scheme implementations provide + different sets of procedures. +- ++</p> + <p> + I have designed a full-featured library of procedures for list processing. + While putting this library together, I checked as many Schemes as I could get +@@ -228,43 +253,47 @@ my hands on. (I have a fair amount of experience with several of these + already.) I missed Chez -- no on-line manual that I can find -- but I hit most + of the other big, full-featured Schemes. The complete list of list-processing + systems I checked is: +-<div class=indent> +- <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> Scheme, MIT Scheme, Gambit, RScheme, MzScheme, slib, ++</p> ++<div class="indent"> ++ <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> Scheme, MIT Scheme, Gambit, RScheme, MzScheme, slib, + <a href="#CommonLisp">Common Lisp</a>, Bigloo, guile, T, APL and the SML standard basis + </div> + <p> + As a result, the library I am proposing is fairly rich. ++</p> + <p> + Following this initial design phase, this library went through several + months of discussion on the SRFI mailing lists, and was altered in light + of the ideas and suggestions put forth during this discussion. ++</p> + <p> + In parallel with designing this API, I have also written a reference + implementation. I have placed this source on the Net with an unencumbered, + "open" copyright. A few notes about the reference implementation: +- ++</p> + <ul> + <li>Although I got procedure names and specs from many Schemes, I wrote this +- code myself. Thus, there are <em>no</em> entanglements. ++ code myself. Thus, there are <em>no</em> entanglements. + Any Scheme implementor + can pick this library up with no worries about copyright problems -- both + commercial and non-commercial systems. + +-<li>The code is written for portability and should be trivial to port to ++</li><li>The code is written for portability and should be trivial to port to + any Scheme. It has only four deviations from <abbr title="Revised^4 Report on Scheme">R4RS</abbr>, clearly discussed + in the comments: <ul> + <li>Use of an <code>error</code> procedure; +- <li>Use of the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> <code>values</code> and a simple <code>receive</code> macro for producing ++ </li><li>Use of the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> <code>values</code> and a simple <code>receive</code> macro for producing + and consuming multiple return values; +- <li>Use of simple <code>:optional</code> and <code>let-optionals</code> macros for optional ++ </li><li>Use of simple <code>:optional</code> and <code>let-optionals</code> macros for optional + argument parsing and defaulting; +- <li>Use of a simple <code>check-arg</code> procedure for argument checking. +- </ul> ++ </li><li>Use of a simple <code>check-arg</code> procedure for argument checking. ++ </li></ul> + +-<li>It is written for clarity and well-commented. The current source is ++</li><li>It is written for clarity and well-commented. The current source is + 768 lines of source code and 826 lines of comments and white space. + +-<li>It is written for efficiency. Fast paths are provided for common ++</li><li><p> ++ It is written for efficiency. Fast paths are provided for common + cases. Side-effecting procedures such as <code>filter!</code> avoid unnecessary, + redundant <code>set-cdr!</code>s which would thrash a generational GC's write barrier + and the store buffers of fast processors. Functions reuse longest common +@@ -272,227 +301,243 @@ implementation. I have placed this source on the Net with an unencumbered, + possible. Constant-space iterations are used in preference to recursions; + local recursions are used in preference to consing temporary intermediate + data structures. +-<p> ++ </p> ++ <p> + This is not to say that the implementation can't be tuned up for + a specific Scheme implementation. There are notes in comments addressing + ways implementors can tune the reference implementation for performance. +-</ul> ++</p></li></ul> + <p> + In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++</p> + + <!--========================================================================--> +-<h1><a name="ProcedureIndex">Procedure Index</a></h1> ++<h2 id="ProcedureIndex">Procedure Index</h2> + <p> + Here is a short list of the procedures provided by the list-lib package. +-<a href="#R5RS">R5RS</a></abbr> procedures are shown in +-<span class=r5rs-proc>bold</span class=r5rs-proc>; +-extended <a href="#R5RS">R5RS</a></abbr> +- procedures, in <span class=r5rs-procx>bold italic</span>. +-<div class=indent> ++<a href="#R5RS">R5RS</a> procedures are shown in ++<span class="r5rs-proc">bold</span>; ++extended <a href="#R5RS">R5RS</a> ++ procedures, in <span class="r5rs-procx">bold italic</span>. ++</p> ++<div class="indent"> + <dl> +-<dt class=proc-index> Constructors +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#cons">cons</a> <a href="#list">list</a></span> +-<a href="#xcons">xcons</a> <a href="#cons*">cons*</a> <a href="#make-list">make-list</a> <a href="#list-tabulate">list-tabulate</a> ++<dt class="proc-index"> Constructors ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#cons">cons</a> <a href="#list">list</a></span> ++<a href="#xcons">xcons</a> <a href="#cons*">cons*</a> <a href="#make-list">make-list</a> <a href="#list-tabulate">list-tabulate</a> + <a href="#list-copy">list-copy</a> <a href="#circular-list">circular-list</a> <a href="#iota">iota</a> + </pre> + +-<dt class=proc-index> Predicates +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#pair-p">pair?</a> <a href="#null-p">null?</a></span> +-<a href="#proper-list-p">proper-list?</a> <a href="#circular-list-p">circular-list?</a> <a href="#dotted-list-p">dotted-list?</a> ++</dd><dt class="proc-index"> Predicates ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#pair-p">pair?</a> <a href="#null-p">null?</a></span> ++<a href="#proper-list-p">proper-list?</a> <a href="#circular-list-p">circular-list?</a> <a href="#dotted-list-p">dotted-list?</a> + <a href="#not-pair-p">not-pair?</a> <a href="#null-list-p">null-list?</a> +-<a href="#list=">list=</a> ++<a href="#list%3D">list=</a> + </pre> + +-<dt class=proc-index> Selectors +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#car">car</a> <a href="#cdr">cdr</a> ... <a href="#cddadr">cddadr</a> <a href="#cddddr">cddddr</a> <a href="#list-ref">list-ref</a></span> ++</dd><dt class="proc-index"> Selectors ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#car">car</a> <a href="#cdr">cdr</a> ... <a href="#cddadr">cddadr</a> <a href="#cddddr">cddddr</a> <a href="#list-ref">list-ref</a></span> + <a href="#first">first</a> <a href="#second">second</a> <a href="#third">third</a> <a href="#fourth">fourth</a> <a href="#fifth">fifth</a> <a href="#sixth">sixth</a> <a href="#seventh">seventh</a> <a href="#eighth">eighth</a> <a href="#ninth">ninth</a> <a href="#tenth">tenth</a> +-<a href="#car+cdr">car+cdr</a> ++<a href="#car%2Bcdr">car+cdr</a> + <a href="#take">take</a> <a href="#drop">drop</a> + <a href="#take-right">take-right</a> <a href="#drop-right">drop-right</a> +-<a href="#take!">take!</a> <a href="#drop-right!">drop-right!</a> +-<a href="#split-at">split-at</a> <a href="#split-at!">split-at!</a> ++<a href="#take!">take!</a> <a href="#drop-right!">drop-right!</a> ++<a href="#split-at">split-at</a> <a href="#split-at!">split-at!</a> + <a href="#last">last</a> <a href="#last-pair">last-pair</a> + </pre> + +-<dt class=proc-index> Miscellaneous: length, append, concatenate, reverse, zip & count +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#length">length</a></span> <a href="#length+">length+</a> +-<span class=r5rs-proc><a href="#append">append</a></span> <a href="#concatenate">concatenate</a> <span class=r5rs-proc><a href="#reverse">reverse</a></span> ++</dd><dt class="proc-index"> Miscellaneous: length, append, concatenate, reverse, zip & count ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#length">length</a></span> <a href="#length%2B">length+</a> ++<span class="r5rs-proc"><a href="#append">append</a></span> <a href="#concatenate">concatenate</a> <span class="r5rs-proc"><a href="#reverse">reverse</a></span> + <a href="#append!">append!</a> <a href="#concatenate!">concatenate!</a> <a href="#reverse!">reverse!</a> + <a href="#append-reverse">append-reverse</a> <a href="#append-reverse!">append-reverse!</a> + <a href="#zip">zip</a> <a href="#unzip1">unzip1</a> <a href="#unzip2">unzip2</a> <a href="#unzip3">unzip3</a> <a href="#unzip4">unzip4</a> <a href="#unzip5">unzip5</a> + <a href="#count">count</a> + </pre> + +-<dt class=proc-index> Fold, unfold & map +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-procx><a href="#map">map</a> <a href="#for-each">for-each</a></span> +-<a href="#fold">fold</a> <a href="#unfold">unfold</a> <a href="#pair-fold">pair-fold</a> <a href="#reduce">reduce</a> +-<a href="#fold-right">fold-right</a> <a href="#unfold-right">unfold-right</a> <a href="#pair-fold-right">pair-fold-right</a> <a href="#reduce-right">reduce-right</a> ++</dd><dt class="proc-index"> Fold, unfold & map ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-procx"><a href="#map">map</a> <a href="#for-each">for-each</a></span> ++<a href="#fold">fold</a> <a href="#unfold">unfold</a> <a href="#pair-fold">pair-fold</a> <a href="#reduce">reduce</a> ++<a href="#fold-right">fold-right</a> <a href="#unfold-right">unfold-right</a> <a href="#pair-fold-right">pair-fold-right</a> <a href="#reduce-right">reduce-right</a> + <a href="#append-map">append-map</a> <a href="#append-map!">append-map!</a> + <a href="#map!">map!</a> <a href="#pair-for-each">pair-for-each</a> <a href="#filter-map">filter-map</a> <a href="#map-in-order">map-in-order</a> + </pre> + +-<dt class=proc-index> Filtering & partitioning +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index"> Filtering & partitioning ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#filter">filter</a> <a href="#partition">partition</a> <a href="#remove">remove</a> +-<a href="#filter!">filter!</a> <a href="#partition!">partition!</a> <a href="#remove!">remove!</a> ++<a href="#filter!">filter!</a> <a href="#partition!">partition!</a> <a href="#remove!">remove!</a> + </pre> + +-<dt class=proc-index> Searching +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-procx><a href="#member">member</a></span> <span class=r5rs-proc><a href="#memq">memq</a> <a href="#memv">memv</a></span> +-<a href="#find">find</a> <a href="#find-tail">find-tail</a> ++</dd><dt class="proc-index"> Searching ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-procx"><a href="#member">member</a></span> <span class="r5rs-proc"><a href="#memq">memq</a> <a href="#memv">memv</a></span> ++<a href="#find">find</a> <a href="#find-tail">find-tail</a> + <a href="#any">any</a> <a href="#every">every</a> + <a href="#list-index">list-index</a> + <a href="#take-while">take-while</a> <a href="#drop-while">drop-while</a> <a href="#take-while!">take-while!</a> + <a href="#span">span</a> <a href="#break">break</a> <a href="#span!">span!</a> <a href="#break!">break!</a> + </pre> + +-<dt class=proc-index> Deleting +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#delete">delete</a> <a href="#delete-duplicates">delete-duplicates</a> ++</dd><dt class="proc-index"> Deleting ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#delete">delete</a> <a href="#delete-duplicates">delete-duplicates</a> + <a href="#delete!">delete!</a> <a href="#delete-duplicates!">delete-duplicates!</a> + </pre> + +-<dt class=proc-index> Association lists +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-procx><a href="#assoc">assoc</a></span> <span class=r5rs-proc><a href="#assq">assq</a> <a href="#assv">assv</a></span> ++</dd><dt class="proc-index"> Association lists ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-procx"><a href="#assoc">assoc</a></span> <span class="r5rs-proc"><a href="#assq">assq</a> <a href="#assv">assv</a></span> + <a href="#alist-cons">alist-cons</a> <a href="#alist-copy">alist-copy</a> + <a href="#alist-delete">alist-delete</a> <a href="#alist-delete!">alist-delete!</a> + </pre> + +-<dt class=proc-index> Set operations on lists +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#lset<=">lset<=</a> <a href="#lset=">lset=</a> <a href="#lset-adjoin">lset-adjoin</a> ++</dd><dt class="proc-index"> Set operations on lists ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#lset%3C%3D">lset<=</a> <a href="#lset%3D">lset=</a> <a href="#lset-adjoin">lset-adjoin</a> + <a href="#lset-union">lset-union</a> <a href="#lset-union!">lset-union!</a> + <a href="#lset-intersection">lset-intersection</a> <a href="#lset-intersection!">lset-intersection!</a> + <a href="#lset-difference">lset-difference</a> <a href="#lset-difference!">lset-difference!</a> + <a href="#lset-xor">lset-xor</a> <a href="#lset-xor!">lset-xor!</a> +-<a href="#lset-diff+intersection">lset-diff+intersection</a> <a href="#lset-diff+intersection!">lset-diff+intersection!</a> ++<a href="#lset-diff%2Bintersection">lset-diff+intersection</a> <a href="#lset-diff%2Bintersection!">lset-diff+intersection!</a> + </pre> + +-<dt class=proc-index> Primitive side-effects +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#set-car!">set-car!</a> <a href="#set-cdr!">set-cdr!</a></span> ++</dd><dt class="proc-index"> Primitive side-effects ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#set-car!">set-car!</a> <a href="#set-cdr!">set-cdr!</a></span> + </pre> +-</dl> ++</dd></dl> + </div> + + <p> + Four <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> list-processing procedures are extended by this library in + backwards-compatible ways: +-<div class=indent> +-<table cellspacing=0> +-<tr valign=baseline><td><code>map for-each</code> +- <td>(Extended to take lists of unequal length) +-<tr valign=baseline><td><code>member assoc</code> +- <td>(Extended to take an optional comparison procedure.) +-</table> ++</p> ++<div class="indent"> ++<table cellspacing="0"> ++<tr valign="baseline"><td><code>map for-each</code> ++ </td><td>(Extended to take lists of unequal length) ++</td></tr><tr valign="baseline"><td><code>member assoc</code> ++ </td><td>(Extended to take an optional comparison procedure.) ++</td></tr></table> + </div> + + <p> + The following <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> list- and pair-processing procedures are also part of + list-lib's exports, as defined by the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>: +-<div class=indent> ++</p> ++<div class="indent"> + <pre> + cons pair? null? +-car cdr ... cdddar cddddr +-set-car! set-cdr! ++car cdr ... cdddar cddddr ++set-car! set-cdr! + list append reverse + length list-ref + memq memv assq assv + </pre> + </div> +- ++ + <p> +-The remaining two <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> list-processing ++The remaining two <abbr title="Revised^4 Report on Scheme">R4RS</abbr>/<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> list-processing + procedures are <em>not</em> part of + this library: +-<div class=indent> +-<table cellspacing=0> +-<tr><td><code>list-tail</code> +- <td>(renamed <code>drop</code>) +-<tr valign=baseline><td><code>list?</code> +- <td>(see <code>proper-list?</code>, +- <code>circular-list?</code> and ++</p> ++<div class="indent"> ++<table cellspacing="0"> ++<tr><td><code>list-tail</code> ++ </td><td>(renamed <code>drop</code>) ++</td></tr><tr valign="baseline"><td><code>list?</code> ++ </td><td>(see <code>proper-list?</code>, ++ <code>circular-list?</code> and + <code>dotted-list?</code>) +-</table> ++</td></tr></table> + </div> + + <!--========================================================================--> +-<h1><a name="GeneralDiscussion">General discussion</a></h1> ++<h2 id="GeneralDiscussion">General discussion</h2> + <p> + + A set of general criteria guided the design of this library. + ++</p> + <p> + +-I don't require "destructive" (what I call "linear update") procedures to ++I don't require "destructive" (what I call "linear update") procedures to + alter and recycle cons cells from the argument lists. They are allowed to, but + not required to. (And the reference implementations I have written <em>do</em> + recycle the argument lists.) + ++</p> + <p> + List-filtering procedures such as <code>filter</code> or <code>delete</code> do not disorder + lists. Elements appear in the answer list in the same order as they appear in + the argument list. This constrains implementation, but seems like a desirable + feature, since in many uses of lists, order matters. (In particular, + disordering an alist is definitely a bad idea.) ++</p> + <p> + Contrariwise, although the reference implementations of the list-filtering + procedures share longest common tails between argument and answer lists, + it not is part of the spec. ++</p> + <p> + Because lists are an inherently sequential data structure (unlike, say, + vectors), list-inspection functions such as <code>find</code>, <code>find-tail</code>, <code>for-each</code>, <code>any</code> + and <code>every</code> commit to a left-to-right traversal order of their argument list. ++</p> + <p> + However, constructor functions, such as <code><code>list-tabulate</code></code> and the mapping + procedures (<code>append-map</code>, <code>append-map!</code>, <code>map!</code>, <code>pair-for-each</code>, <code>filter-map</code>, + <code>map-in-order</code>), do <em>not</em> specify the dynamic order in which their procedural + argument is applied to its various values. ++</p> + <p> + Predicates return useful true values wherever possible. Thus <code>any</code> must return + the true value produced by its predicate, and <code>every</code> returns the final true + value produced by applying its predicate argument to the last element of its + argument list. ++</p> + <p> + Functionality is provided both in pure and linear-update (potentially + destructive) forms wherever this makes sense. ++</p> + <p> + No special status accorded Scheme's built-in equality functions. + Any functionality provided in terms of <code>eq?</code>, <code>eqv?</code>, <code>equal?</code> is also + available using a client-provided equality function. ++</p> + <p> + Proper design counts for more than backwards compatibility, but I have tried, +-<em>ceteris paribus</em>, ++<em>ceteris paribus</em>, + to be as backwards-compatible as possible with existing + list-processing libraries, in order to facilitate porting old code to run as a + client of the procedures in this library. Name choices and semantics are, for + the most part, in agreement with existing practice in many current Scheme + systems. I have indicated some incompatibilities in the following text. ++</p> + <p> + These procedures are <em>not</em> "sequence generic" -- <em>i.e.</em>, procedures that + operate on either vectors and lists. They are list-specific. I prefer to + keep the library simple and focussed. ++</p> + <p> + I have named these procedures without a qualifying initial "list-" lexeme, + which is in keeping with the existing set of list-processing utilities in +@@ -501,9 +546,11 @@ I follow the general Scheme convention (vector-length, string-ref) of + placing the type-name before the action when naming procedures -- so + we have <code>list-copy</code> and <code>pair-for-each</code> rather than the perhaps + more fluid, but less consistent, <code>copy-list</code> or <code>for-each-pair</code>. ++</p> + <p> + I have generally followed a regular and consistent naming scheme, composing + procedure names from a set of basic lexemes. ++</p> + + <!--========================================================================--> + <h2><a name="LinearUpdateProcedures">"Linear update" procedures</a></h2> +@@ -520,18 +567,21 @@ of <var>list<sub>1</sub></var> to point to <var>list<sub>2</sub></var>, and then + empty list, in which case it would simply return <var>list<sub>2</sub></var>). However, <code>append!</code> may + also elect to perform a pure append operation -- this is a legal definition + of <code>append!</code>: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define append! append) + </pre> + <p> + This is why we do not call these procedures "destructive" -- because they + aren't <em>required</em> to be destructive. They are <em>potentially</em> destructive. ++</p> + <p> + What this means is that you may only apply linear-update procedures to + values that you know are "dead" -- values that will never be used again + in your program. This must be so, since you can't rely on the value passed + to a linear-update procedure after that procedure has been called. It + might be unchanged; it might be altered. ++</p> + <p> + The "linear" in "linear update" doesn't mean "linear time" or "linear space" + or any sort of multiple-of-n kind of meaning. It's a fancy term that +@@ -542,6 +592,7 @@ bound to no other variable. So when you <em>use</em> a variable in a variable + reference, you "use it up." Knowing that no one else has a pointer to that + value means the a system primitive is free to side-effect its arguments to + produce what is, observationally, a pure-functional result. ++</p> + <p> + In the context of this library, "linear update" means you, the programmer, + know there are <em>no other</em> live references to the value passed to the +@@ -549,11 +600,13 @@ procedure -- after passing the value to one of these procedures, the + value of the old pointer is indeterminate. Basically, you are licensing + the Scheme implementation to alter the data structure if it feels like + it -- you have declared you don't care either way. ++</p> + <p> + You get no help from Scheme in checking that the values you claim are "linear" + really are. So you better get it right. Or play it safe and use the non-! + procedures -- it doesn't do any good to compute quickly if you get the wrong + answer. ++</p> + <p> + Why go to all this trouble to define the notion of "linear update" and use it + in a procedure spec, instead of the more common notion of a "destructive" +@@ -572,16 +625,18 @@ algorithm. Linear-update operations are easily parallelised. Going with a + linear-update spec doesn't close off these valuable alternative implementation + techniques. This list library is intended as a set of low-level, basic + operators, so we don't want to exclude these possible implementations. ++</p> + <p> + The linear-update procedures in this library are +-<div class=indent><code> ++</p> ++<div class="indent"><code> + take! drop-right! split-at! + append! concatenate! reverse! append-reverse! + append-map! map! +-filter! partition! remove! ++filter! partition! remove! + take-while! span! break! + delete! alist-delete! delete-duplicates! +-lset-adjoin! lset-union! lset-intersection! ++lset-adjoin! lset-union! lset-intersection! + lset-difference! lset-xor! lset-diff+intersection! + </code></div> + +@@ -597,26 +652,33 @@ treat these trees as lists. Further complications ensue from the fact that + Scheme allows side-effects to these tuples, raising the possibility of lists + of unbounded length, and trees of unbounded depth (that is, circular data + structures). +- ++</p> + <p> + However, there is a simple view of the world of Scheme values that considers + every value to be a list of some sort. that is, every value is either ++</p> + <ul> +- <li>a "proper list" -- a finite, nil-terminated list, such as:<br> +- <code>(a b c)</code><br> +- <code>()</code><br> +- <code>(32)</code><br> +- <li>a "dotted list" -- a finite, non-nil terminated list, such as:<br> +- <code>(a b c . d)</code><br> +- <code>(x . y)</code><br> +- <code>42</code><br> +- <code>george</code><br> +- <li>or a "circular list" -- an infinite, unterminated list. ++ <li> ++ a "proper list" -- a finite, nil-terminated list, such as:<br /> ++ <code>(a b c)</code><br /> ++ <code>()</code><br /> ++ <code>(32)</code><br /> ++ </li> ++ <li> ++ a "dotted list" -- a finite, non-nil terminated list, such as:<br /> ++ <code>(a b c . d)</code><br /> ++ <code>(x . y)</code><br /> ++ <code>42</code><br /> ++ <code>george</code><br /> ++ </li> ++ <li> ++ or a "circular list" -- an infinite, unterminated list. ++ </li> + </ul> + <p> + Note that the zero-length dotted lists are simply all the non-null, non-pair + values. +- ++</p> + <p> + This view is captured by the predicates <code>proper-list?</code>, <code>dotted-list?</code>, and + <code>circular-list?</code>. List-lib users should note that dotted lists are not commonly +@@ -624,7 +686,7 @@ used, and are considered by many Scheme programmers to be an ugly artifact of + Scheme's lack of a true list type. However, dotted lists do play a noticeable + role in the <em>syntax</em> of Scheme, in the "rest" parameters used by n-ary + lambdas: <code>(lambda (x y . rest) ...)</code>. +- ++</p> + <p> + Dotted lists are <em>not</em> fully supported by list-lib. Most procedures are + defined only on proper lists -- that is, finite, nil-terminated lists. The +@@ -632,8 +694,9 @@ procedures that will also handle circular or dotted lists are specifically + marked. While this design decision restricts the domain of possible arguments + one can pass to these procedures, it has the benefit of allowing the + procedures to catch the error cases where programmers inadvertently pass +-scalar values to a list procedure by accident, ++scalar values to a list procedure by accident, + <em>e.g.</em>, by switching the arguments to a procedure call. ++</p> + + <!--========================================================================--> + <h2><a name="Errors">Errors</a></h2> +@@ -645,6 +708,7 @@ do that." They are not a guarantee that a conforming implementation will + Regrettably, <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> Scheme requires no firmer guarantee even for basic operators such + as <code>car</code> and <code>cdr</code>, so there's little point in requiring these procedures to do + more. Here is the relevant section of the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>: ++</p> + <blockquote> + <p> + When speaking of an error situation, this report uses the phrase "an +@@ -654,209 +718,235 @@ more. Here is the relevant section of the <abbr title="Revised^5 Report on Sche + report the error, though they are encouraged to do so. An error + situation that implementations are not required to detect is usually + referred to simply as "an error." +- <p> ++ </p><p> + For example, it is an error for a procedure to be passed an argument + that the procedure is not explicitly specified to handle, even though + such domain errors are seldom mentioned in this report. + Implementations may extend a procedure's domain of definition to + include such arguments. +-</blockquote> ++</p></blockquote> + + + <!--========================================================================--> + <h2><a name="NotIncludedInThisLibrary">Not included in this library</a></h2> + <p> + The following items are not in this library: ++</p> + <ul> + <li>Sort routines +-<li>Destructuring/pattern-matching macro +-<li>Tree-processing routines +-</ul> ++</li><li>Destructuring/pattern-matching macro ++</li><li>Tree-processing routines ++</li></ul> + <p> + They should have their own <abbr title="Scheme Request for Implementation">SRFI</abbr> specs. +-<p> ++</p> + + + <!--========================================================================--> +-<h1><a name="TheProcedures">The procedures</a></h1> ++<h2 id="TheProcedures">The procedures</h2> + <p> + + In a Scheme system that has a module or package system, these procedures + should be contained in a module named "list-lib". +- ++</p> ++<p> + The templates given below obey the following conventions for procedure formals: ++</p> + <table> +-<tr valign=baseline><th align=left> <var>list</var> +- <td> A proper (finite, nil-terminated) list +-<tr valign=baseline><th align=left> <var>clist</var> +- <td> A proper or circular list +-<tr valign=baseline><th align=left> <var>flist</var> +- <td> A finite (proper or dotted) list +-<tr valign=baseline><th align=left> <var>pair</var> +- <td> A pair +-<tr valign=baseline> +- <th align=left> <var>x</var>, <var>y</var>, <var>d</var>, <var>a</var> +- <td> Any value +-<tr valign=baseline><th align=left> <var>object</var>, <var>value</var> +- <td> Any value +-<tr valign=baseline><th align=left> <var>n</var>, <var>i</var> +- <td> A natural number (an integer >= 0) +-<tr valign=baseline><th align=left> <var>proc</var> +- <td> A procedure +-<tr valign=baseline><th align=left> <var>pred</var> +- <td> A procedure whose return value is treated as a boolean +-<tr valign=baseline><th align=left> <var>=</var> +- <td> A boolean procedure taking two arguments +-</table> ++<tr valign="baseline"><th align="left"> <var>list</var> ++ </th><td> A proper (finite, nil-terminated) list ++</td></tr><tr valign="baseline"><th align="left"> <var>clist</var> ++ </th><td> A proper or circular list ++</td></tr><tr valign="baseline"><th align="left"> <var>flist</var> ++ </th><td> A finite (proper or dotted) list ++</td></tr><tr valign="baseline"><th align="left"> <var>pair</var> ++ </th><td> A pair ++</td></tr><tr valign="baseline"> ++ <th align="left"> <var>x</var>, <var>y</var>, <var>d</var>, <var>a</var> ++ </th><td> Any value ++</td></tr><tr valign="baseline"><th align="left"> <var>object</var>, <var>value</var> ++ </th><td> Any value ++</td></tr><tr valign="baseline"><th align="left"> <var>n</var>, <var>i</var> ++ </th><td> A natural number (an integer >= 0) ++</td></tr><tr valign="baseline"><th align="left"> <var>proc</var> ++ </th><td> A procedure ++</td></tr><tr valign="baseline"><th align="left"> <var>pred</var> ++ </th><td> A procedure whose return value is treated as a boolean ++</td></tr><tr valign="baseline"><th align="left"> <var>=</var> ++ </th><td> A boolean procedure taking two arguments ++</td></tr></table> + + <p> + It is an error to pass a circular or dotted list to a procedure not + defined to accept such an argument. +- ++</p> + <!--========================================================================--> +-<h2><a name="Constructors">Constructors</a></h2> +-<p> ++<h2 id="Constructors">Constructors</h2> ++ + + <dl> + + <!-- + ==== cons + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="cons"></a> +-<code class=proc-def>cons</code> <var>a d -> pair</var> +-<dd class=proc-def> ++<code class="proc-def">cons</code> <var>a d -> pair</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] +- The primitive constructor. Returns a newly allocated pair whose car is +- <var>a</var> and whose cdr is <var>d</var>. ++ The primitive constructor. Returns a newly allocated pair whose car is ++ <var>a</var> and whose cdr is <var>d</var>. + The pair is guaranteed to be different (in the sense of <code>eqv?</code>) + from every existing object. +-<pre class=code-example> +-(cons 'a '()) => (a) +-(cons '(a) '(b c d)) => ((a) b c d) +-(cons "a" '(b c)) => ("a" b c) +-(cons 'a 3) => (a . 3) +-(cons '(a b) 'c) => ((a b) . c) ++</p> ++<pre class="code-example"> ++(cons 'a '()) => (a) ++(cons '(a) '(b c d)) => ((a) b c d) ++(cons "a" '(b c)) => ("a" b c) ++(cons 'a 3) => (a . 3) ++(cons '(a b) 'c) => ((a b) . c) + </pre> +- ++</dd> + <!-- + ==== list + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="list"></a> +-<code class=proc-def>list</code> <var>object ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">list</code> <var>object ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns a newly allocated list of its arguments. +-<pre class=code-example> +-(list 'a (+ 3 4) 'c) => (a 7 c) +-(list) => () ++</p> ++<pre class="code-example"> ++(list 'a (+ 3 4) 'c) => (a 7 c) ++(list) => () + </pre> +- ++</dd> + <!-- + ==== xcons + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="xcons"></a> +-<code class=proc-def>xcons</code> <var>d a -> pair</var> +-<dd class=proc-def> ++<code class="proc-def">xcons</code> <var>d a -> pair</var> ++</dt> ++<dd class="proc-def"> + <pre> + (lambda (d a) (cons a d)) + </pre> +- Of utility only as a value to be conveniently passed to higher-order ++<p> ++ Of utility only as a value to be conveniently passed to higher-order + procedures. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (xcons '(b c) 'a) => (a b c) + </pre> +- ++<p> + The name stands for "eXchanged CONS." +- ++</p> ++</dd> + <!-- + ==== cons* + ============================================================================--> +-<a name="cons*"></a> +-<dt class=proc-def><code class=proc-def>cons*</code><var> elt<sub>1</sub> elt<sub>2</sub> ... -> object</var> +-<dd class=proc-def> +- +- Like <code>list</code>, ++<dt class="proc-def" id="cons*"><code class="proc-def">cons*</code><var> elt<sub>1</sub> elt<sub>2</sub> ... -> object</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Like <code>list</code>, + but the last argument provides the tail of the constructed list, + returning +- <div class=indent><code> ++</p> ++ <div class="indent"><code> + (cons <var>elt<sub>1</sub></var> (cons <var>elt<sub>2</sub></var> (cons ... <var>elt<sub>n</sub></var>))) + </code></div> +- This function is called <code>list*</code> in <a href="#CommonLisp">Common Lisp</a> and about ++<p> ++ This function is called <code>list*</code> in <a href="#CommonLisp">Common Lisp</a> and about + half of the Schemes that provide it, + and <code>cons*</code> in the other half. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (cons* 1 2 3 4) => (1 2 3 . 4) + (cons* 1) => 1 + </pre> +- ++</dd> + <!-- + ==== make-list + ============================================================================--> +-<a name="make-list"></a> +-<dt class=proc-def> <code class=proc-def>make-list</code> <var>n [fill] -> list</var> +-<dd class=proc-def> +- Returns an <var>n</var>-element list, ++<dt class="proc-def" id="make-list"> <code class="proc-def">make-list</code> <var>n [fill] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Returns an <var>n</var>-element list, + whose elements are all the value <var>fill</var>. + If the <var>fill</var> argument is not given, the elements of the list may + be arbitrary values. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (make-list 4 'c) => (c c c c) + </pre> +- ++</dd> + <!-- + ==== list-tabulate + ============================================================================--> +-<a name="list-tabulate"></a> +-<dt class=proc-def><code class=proc-def>list-tabulate</code><var> n init-proc -> list</var> +-<dd class=proc-def> ++<dt class="proc-def" id="list-tabulate"><code class="proc-def">list-tabulate</code><var> n init-proc -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns an <var>n</var>-element list. Element <var>i</var> of the list, where 0 <= <var>i</var> < <var>n</var>, + is produced by <code>(<var>init-proc</var> <var>i</var>)</code>. No guarantee is made about the dynamic + order in which <var>init-proc</var> is applied to these indices. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (list-tabulate 4 values) => (0 1 2 3) + </pre> +- ++</dd> + <!-- + ==== list-copy + ============================================================================--> +-<a name="list-copy"></a> +-<dt class=proc-def><code class=proc-def>list-copy</code><var> flist -> flist</var> +-<dd class=proc-def> ++<dt class="proc-def" id="list-copy"><code class="proc-def">list-copy</code><var> flist -> flist</var> ++</dt> ++<dd class="proc-def"> ++<p> + Copies the spine of the argument. +- ++</p> ++</dd> + <!-- + ==== circular-list + ============================================================================--> +-<a name="circular-list"></a> +-<dt class=proc-def><code class=proc-def>circular-list</code><var> elt<sub>1</sub> elt<sub>2</sub> ... -> list</var> +-<dd class=proc-def> ++<dt class="proc-def" id="circular-list"><code class="proc-def">circular-list</code><var> elt<sub>1</sub> elt<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Constructs a circular list of the elements. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (circular-list 'z 'q) => (z q z q z q ...) + </pre> +- ++</dd> + <!-- + ==== iota + ============================================================================--> +-<a name="iota"></a> +-<dt class=proc-def><code class=proc-def>iota</code><var> count [start step] -> list</var> +-<dd class=proc-def> ++<dt class="proc-def" id="iota"><code class="proc-def">iota</code><var> count [start step] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns a list containing the elements +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (<var>start</var> <var>start</var>+<var>step</var> ... <var>start</var>+(<var>count</var>-1)*<var>step</var>) + </pre> ++<p> + The <var>start</var> and <var>step</var> parameters default to 0 and 1, respectively. + This procedure takes its name from the APL primitive. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (iota 5) => (0 1 2 3 4) + (iota 5 0 -0.1) => (0 -0.1 -0.2 -0.3 -0.4) + </pre> ++</dd> + </dl> + + <!--========================================================================--> +@@ -864,240 +954,282 @@ defined to accept such an argument. + <p> + Note: the predicates <code>proper-list?</code>, <code>circular-list?</code>, and <code>dotted-list?</code> + partition the entire universe of Scheme values. +- ++</p> + <dl> + <!-- + ==== proper-list? + ============================================================================--> +-<dt class=proc-def> +-<code class=proc-def>proper-list?</code><var> x -> boolean</var> ++<dt class="proc-def"> ++<code class="proc-def">proper-list?</code><var> x -> boolean</var> + <a name="proper-list-p"></a> +-<dd class=proc-def> ++</dt> ++<dd class="proc-def"> ++<p> + Returns true iff <var>x</var> is a proper list -- a finite, nil-terminated list. ++</p> + <p> +- More carefully: The empty list is a proper list. A pair whose cdr is a ++ More carefully: The empty list is a proper list. A pair whose cdr is a + proper list is also a proper list: ++</p> + <pre> + <proper-list> ::= () (Empty proper list) + | (cons <x> <proper-list>) (Proper-list pair) + </pre> ++<p> + Note that this definition rules out circular lists. This + function is required to detect this case and return false. ++</p> + <p> + Nil-terminated lists are called "proper" lists by <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> and <a href="#CommonLisp">Common Lisp</a>. + The opposite of proper is improper. ++</p> + <p> + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> binds this function to the variable <code>list?</code>. +-<p> ++</p> + <pre> + (not (proper-list? <var>x</var>)) = (or (dotted-list? <var>x</var>) (circular-list? <var>x</var>)) + </pre> +- ++</dd> + <!-- + ==== circular-list? + ============================================================================--> +-<a name="circular-list-p"></a> +-<dt class=proc-def><code class=proc-def>circular-list?</code><var> x -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def" id="circular-list-p"><code class="proc-def">circular-list?</code><var> x -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + True if <var>x</var> is a circular list. A circular list is a value such that + for every <var>n</var> >= 0, cdr<sup><var>n</var></sup>(<var>x</var>) is a pair. ++</p> + <p> + Terminology: The opposite of circular is finite. ++</p> + <pre> + (not (circular-list? <var>x</var>)) = (or (proper-list? <var>x</var>) (dotted-list? <var>x</var>)) + </pre> +- ++</dd> + <!-- + ==== dotted-list? + ============================================================================--> +-<a name="dotted-list-p"></a> +-<dt class=proc-def><code class=proc-def>dotted-list?</code><var> x -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def" id="dotted-list-p"><code class="proc-def">dotted-list?</code><var> x -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + True if <var>x</var> is a finite, non-nil-terminated list. That is, there exists +- an <var>n</var> >= 0 such that cdr<sup><var>n</var></sup>(<var>x</var>) is neither a pair nor (). ++ an <var>n</var> >= 0 such that cdr<sup><var>n</var></sup>(<var>x</var>) is neither a pair nor (). + This includes +- non-pair, non-() values (<em>e.g.</em> symbols, numbers), ++ non-pair, non-() values (<em>e.g.</em> symbols, numbers), + which are considered to be dotted lists of length 0. ++</p> + <pre> + (not (dotted-list? <var>x</var>)) = (or (proper-list? <var>x</var>) (circular-list? <var>x</var>)) + </pre> +- ++</dd> + <!-- + ==== pair? + ============================================================================--> +-<a name="pair-p"></a> +-<dt class=proc-def><code class=proc-def>pair?</code><var> object -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def" id="pair-p"><code class="proc-def">pair?</code><var> object -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns #t if <var>object</var> is a pair; otherwise, #f. +-<pre class=code-example> +-(pair? '(a . b)) => #t +-(pair? '(a b c)) => #t +-(pair? '()) => #f +-(pair? '#(a b)) => #f +-(pair? 7) => #f +-(pair? 'a) => #f ++</p> ++<pre class="code-example"> ++(pair? '(a . b)) => #t ++(pair? '(a b c)) => #t ++(pair? '()) => #f ++(pair? '#(a b)) => #f ++(pair? 7) => #f ++(pair? 'a) => #f + </pre> +- ++</dd> + <!-- + ==== null? + ============================================================================--> +-<a name="null-p"></a> +-<dt class=proc-def><code class=proc-def>null?</code><var> object -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def" id="null-p"><code class="proc-def">null?</code><var> object -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns #t if <var>object</var> is the empty list; otherwise, #f. +- ++</p> ++</dd> + <!-- + ==== null-list? + ============================================================================--> +-<a name="null-list-p"></a> +-<dt class=proc-def><code class=proc-def>null-list?</code><var> list -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def" id="null-list-p"><code class="proc-def">null-list?</code><var> list -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + <var>List</var> is a proper or circular list. This procedure returns true if + the argument is the empty list (), and false otherwise. It is an + error to pass this procedure a value which is not a proper or + circular list. +- +- This procedure is recommended as the termination condition for ++</p> ++<p> ++ This procedure is recommended as the termination condition for + list-processing procedures that are not defined on dotted lists. +- ++</p> ++</dd> + <!-- + ==== not-pair? + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="not-pair-p"></a> +-<code class=proc-def>not-pair?</code><var> x -> boolean</var> +-<dd class=proc-def> +- <pre>(lambda (x) (not (pair? x)))</pre> ++<code class="proc-def">not-pair?</code><var> x -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<pre>(lambda (x) (not (pair? x)))</pre> ++<p> + Provided as a procedure as it can be useful as the termination condition + for list-processing procedures that wish to handle all finite lists, + both proper and dotted. +- ++</p> ++</dd> + <!-- + ==== list= + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="list="></a> +-<code class=proc-def>list=</code><var> elt= list<sub>1</sub> ... -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">list=</code><var> elt= list<sub>1</sub> ... -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Determines list equality, given an element-equality procedure. +- Proper list <var>A</var> equals proper list <var>B</var> ++ Proper list <var>A</var> equals proper list <var>B</var> + if they are of the same length, +- and their corresponding elements are equal, +- as determined by <var>elt=</var>. ++ and their corresponding elements are equal, ++ as determined by <var>elt=</var>. + If the element-comparison procedure's first argument is +- from <var>list<sub>i</sub></var>, +- then its second argument is from <var>list<sub>i+1</sub></var>, ++ from <var>list<sub>i</sub></var>, ++ then its second argument is from <var>list<sub>i+1</sub></var>, + <em>i.e.</em> it is always called as + <code>(<var>elt=</var> <var>a</var> <var>b</var>)</code> +- for <var>a</var> an element of list <var>A</var>, ++ for <var>a</var> an element of list <var>A</var>, + and <var>b</var> an element of list <var>B</var>. ++</p> + <p> +- In the <var>n</var>-ary case, +- every <var>list<sub>i</sub></var> is compared to +- <var>list<sub>i+1</sub></var> +- (as opposed, for example, to comparing +- <var>list<sub>1</sub></var> to every <var>list<sub>i</sub></var>, +- for <var>i</var>>1). +- If there are no list arguments at all, ++ In the <var>n</var>-ary case, ++ every <var>list<sub>i</sub></var> is compared to ++ <var>list<sub>i+1</sub></var> ++ (as opposed, for example, to comparing ++ <var>list<sub>1</sub></var> to every <var>list<sub>i</sub></var>, ++ for <var>i</var>>1). ++ If there are no list arguments at all, + <code>list=</code> simply returns true. ++</p> + <p> + It is an error to apply <code>list=</code> to anything except proper lists. + While + implementations may choose to extend it to circular lists, note that it + cannot reasonably be extended to dotted lists, as it provides no way to + specify an equality procedure for comparing the list terminators. ++</p> + <p> + Note that the dynamic order in which the <var>elt=</var> procedure is +- applied to pairs of elements is not specified. ++ applied to pairs of elements is not specified. + For example, if <code>list=</code> is applied +- to three lists, <var>A</var>, <var>B</var>, and <var>C</var>, ++ to three lists, <var>A</var>, <var>B</var>, and <var>C</var>, + it may first completely compare <var>A</var> to <var>B</var>, +- then compare <var>B</var> to <var>C</var>, ++ then compare <var>B</var> to <var>C</var>, + or it may compare the first elements of <var>A</var> and <var>B</var>, +- then the first elements of <var>B</var> and <var>C</var>, ++ then the first elements of <var>B</var> and <var>C</var>, + then the second elements of <var>A</var> and <var>B</var>, and so forth. ++</p> + <p> +- The equality procedure must be consistent with <code>eq?</code>. ++ The equality procedure must be consistent with <code>eq?</code>. + That is, it must be the case that +-<div class=indent> +- <code>(eq? <var>x</var> <var>y</var>)</code> => <code>(<var>elt=</var> <var>x</var> <var>y</var>)</code>. ++</p> ++<div class="indent"> ++ <code>(eq? <var>x</var> <var>y</var>)</code> => <code>(<var>elt=</var> <var>x</var> <var>y</var>)</code>. + </div> +- Note that this implies that two lists which are <code>eq?</code> ++<p> ++ Note that this implies that two lists which are <code>eq?</code> + are always <var>list=</var>, as well; implementations may exploit this + fact to "short-cut" the element-by-element comparisons. +-<pre class=code-example> +-(list= eq?) => #t ; Trivial cases +-(list= eq? '(a)) => #t ++</p> ++<pre class="code-example"> ++(list= eq?) => #t ; Trivial cases ++(list= eq? '(a)) => #t + </pre> +- ++</dd> + </dl> + + + <!--========================================================================--> +-<h2><a name="Selectors">Selectors</a></h2> ++<h2 id="Selectors">Selectors</h2> + <dl> + + <!-- + ==== car cdr + ============================================================================--> +-<a name="car"></a> +-<a name="cdr"></a> +-<dt class=proc-def1><code class=proc-def>car</code><var> pair -> value</var> +-<dt class=proc-defn><code class=proc-def>cdr</code><var> pair -> value</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="car"><code class="proc-def">car</code><var> pair -> value</var> ++</dt> ++<dt class="proc-defn" id="cdr"><code class="proc-def">cdr</code><var> pair -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + These functions return the contents of the car and cdr field of their + argument, respectively. + Note that it is an error to apply them to the empty list. +-<pre class=code-example> +-(car '(a b c)) => a (cdr '(a b c)) => (b c) +-(car '((a) b c d)) => (a) (cdr '((a) b c d)) => (b c d) +-(car '(1 . 2)) => 1 (cdr '(1 . 2)) => 2 +-(car '()) => *error* (cdr '()) => *error* ++</p> ++<pre class="code-example"> ++(car '(a b c)) => a (cdr '(a b c)) => (b c) ++(car '((a) b c d)) => (a) (cdr '((a) b c d)) => (b c d) ++(car '(1 . 2)) => 1 (cdr '(1 . 2)) => 2 ++(car '()) => *error* (cdr '()) => *error* + </pre> +- ++</dd> + + + <!-- + ==== caar cadr ... cdddar cddddr + ============================================================================--> +-<a name="caar"></a> +-<a name="cadr"></a> +-<a name="cdddar"></a> +-<a name="cddddr"></a> +-<dt class=proc-def1><code class=proc-def>caar</code><var> pair -> value</var> +-<dt class=proc-defi><code class=proc-def>cadr</code><var> pair -> value</var> +-<dt class=proc-defi><code class=proc-def>:</code> +-<dt class=proc-defi><code class=proc-def>cdddar</code><var> pair -> value</var> +-<dt class=proc-defn><code class=proc-def>cddddr</code><var> pair -> value</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="caar"><code class="proc-def">caar</code><var> pair -> value</var> ++</dt> ++<dt class="proc-defi" id="cadr"><code class="proc-def">cadr</code><var> pair -> value</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">:</code> ++</dt> ++<dt class="proc-defi" id="cddadr"><code class="proc-def">cddadr</code><var> pair -> value</var> ++</dt> ++<dt class="proc-defi" id="cdddar"><code class="proc-def">cdddar</code><var> pair -> value</var> ++</dt> ++<dt class="proc-defn" id="cddddr"><code class="proc-def">cddddr</code><var> pair -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + These procedures are compositions of <code>car</code> and <code>cdr</code>, + where for example <code>caddr</code> could be defined by +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define caddr (lambda (x) (car (cdr (cdr x))))). + </pre> ++<p> + Arbitrary compositions, up to four deep, are provided. There are + twenty-eight of these procedures in all. +- ++</p> ++</dd> + <!-- + ==== list-ref + ============================================================================--> +-<a name="list-ref"></a> +-<dt class=proc-def><code class=proc-def>list-ref</code><var> clist i -> value</var> +-<dd class=proc-def> ++<dt class="proc-def" id="list-ref"><code class="proc-def">list-ref</code><var> clist i -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] +- Returns the <var>i</var><sup>th</sup> element of <var>clist</var>. +- (This is the same as the car of ++ Returns the <var>i</var><sup>th</sup> element of <var>clist</var>. ++ (This is the same as the car of + <code>(drop <var>clist</var> <var>i</var>)</code>.) +- It is an error if <var>i</var> >= <var>n</var>, ++ It is an error if <var>i</var> >= <var>n</var>, + where <var>n</var> is the length of <var>clist</var>. +-<pre class=code-example> +-(list-ref '(a b c d) 2) => c +-</pre> +- ++</p> ++<pre class="code-example"> ++(list-ref '(a b c d) 2) => c ++</pre> ++</dd> + <!-- + ==== tenth + ==== ninth +@@ -1110,75 +1242,75 @@ partition the entire universe of Scheme values. + ==== second + ==== first + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="first"></a> +-<code class=proc-def>first </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">first </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="second"></a> +-<code class=proc-def>second </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">second </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="third"></a> +-<code class=proc-def>third </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">third </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="fourth"></a> +-<code class=proc-def>fourth </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">fourth </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="fifth"></a> +-<code class=proc-def>fifth </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">fifth </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="sixth"></a> +-<code class=proc-def>sixth </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">sixth </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="seventh"></a> +-<code class=proc-def>seventh </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">seventh </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="eighth"></a> +-<code class=proc-def>eighth </code><var>pair -> object </var> +-<dt class=proc-defi> ++<code class="proc-def">eighth </code><var>pair -> object </var> ++</dt><dt class="proc-defi"> + <a name="ninth"></a> +-<code class=proc-def>ninth </code><var>pair -> object </var> +-<dt class=proc-defn> ++<code class="proc-def">ninth </code><var>pair -> object </var> ++</dt><dt class="proc-defn"> + <a name="tenth"></a> +-<code class=proc-def>tenth </code><var>pair -> object </var> +-<dd class=proc-def> +- Synonyms for <code>car</code>, <code>cadr</code>, <code>caddr</code>, ... ++<code class="proc-def">tenth </code><var>pair -> object </var> ++</dt><dd class="proc-def"> ++ Synonyms for <code>car</code>, <code>cadr</code>, <code>caddr</code>, ... + +-<pre class=code-example> ++<pre class="code-example"> + (third '(a b c d e)) => c + </pre> + + <!-- + ==== car+cdr + ============================================================================--> +-<dt class=proc-def> ++</dd><dt class="proc-def"> + <a name="car+cdr"></a> +-<code class=proc-def>car+cdr</code><var> pair -> [x y]</var> +-<dd class=proc-def> ++<code class="proc-def">car+cdr</code><var> pair -> [x y]</var> ++</dt><dd class="proc-def"> + The fundamental pair deconstructor: +-<pre class=code-example> ++<pre class="code-example"> + (lambda (p) (values (car p) (cdr p))) + </pre> + This can, of course, be implemented more efficiently by a compiler. +- ++</dd> + <!-- + ==== drop + ==== take + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="take"></a> +-<code class=proc-def>take</code><var> x i -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">take</code><var> x i -> list</var> ++</dt><dt class="proc-defn"> + <a name="drop"></a> +-<code class=proc-def>drop</code><var> x i -> object</var> +-<dd class=proc-def> +- <code>take</code> returns the first <var>i</var> elements of list <var>x</var>.<br> ++<code class="proc-def">drop</code><var> x i -> object</var> ++</dt><dd class="proc-def"> ++ <code>take</code> returns the first <var>i</var> elements of list <var>x</var>.<br /> + <code>drop</code> returns all but the first <var>i</var> elements of list <var>x</var>. +-<pre class=code-example> ++<pre class="code-example"> + (take '(a b c d e) 2) => (a b) + (drop '(a b c d e) 2) => (c d e) + </pre> + <var>x</var> may be any value -- a proper, circular, or dotted list: +-<pre class=code-example> ++<pre class="code-example"> + (take '(1 2 3 . d) 2) => (1 2) + (drop '(1 2 3 . d) 2) => (3 . d) + (take '(1 2 3 . d) 3) => (1 2 3) +@@ -1186,7 +1318,7 @@ partition the entire universe of Scheme values. + </pre> + For a legal <var>i</var>, <code>take</code> and <code>drop</code> partition the list in a manner which + can be inverted with <code>append</code>: +-<pre class=code-example> ++<pre class="code-example"> + (append (take <var>x</var> <var>i</var>) (drop <var>x</var> <var>i</var>)) = <var>x</var> + </pre> + <code>drop</code> is exactly equivalent to performing <var>i</var> cdr operations on <var>x</var>; +@@ -1195,114 +1327,138 @@ partition the entire universe of Scheme values. + If the argument is a list of non-zero length, <code>take</code> is guaranteed to + return a freshly-allocated list, even in the case where the entire + list is taken, <em>e.g.</em> <code>(take lis (length lis))</code>. +- ++</dd> + <!-- + ==== drop-right + ==== take-right + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="take-right"></a> +-<code class=proc-def>take-right</code><var> flist i -> object</var> +-<dt class=proc-defn> ++<code class="proc-def">take-right</code><var> flist i -> object</var> ++</dt> ++<dt class="proc-defn"> + <a name="drop-right"></a> +-<code class=proc-def>drop-right</code><var> flist i -> list</var> +-<dd class=proc-def> +- <code>take-right</code> returns the last <var>i</var> elements of <var>flist</var>.<br> ++<code class="proc-def">drop-right</code><var> flist i -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <code>take-right</code> returns the last <var>i</var> elements of <var>flist</var>.<br /> + <code>drop-right</code> returns all but the last <var>i</var> elements of <var>flist</var>. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (take-right '(a b c d e) 2) => (d e) + (drop-right '(a b c d e) 2) => (a b c) + </pre> ++<p> + The returned list may share a common tail with the argument list. ++</p> + <p> + <var>flist</var> may be any finite list, either proper or dotted: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (take-right '(1 2 3 . d) 2) => (2 3 . d) + (drop-right '(1 2 3 . d) 2) => (1) + (take-right '(1 2 3 . d) 0) => d + (drop-right '(1 2 3 . d) 0) => (1 2 3) + </pre> +- For a legal <var>i</var>, <code>take-right</code> and <code>drop-right</code> partition the list in a manner ++<p> ++ For a legal <var>i</var>, <code>take-right</code> and <code>drop-right</code> partition the list in a manner + which can be inverted with <code>append</code>: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (append (take <var>flist</var> <var>i</var>) (drop <var>flist</var> <var>i</var>)) = <var>flist</var> + </pre> ++<p> + <code>take-right</code>'s return value is guaranteed to share a common tail with <var>flist</var>. + + If the argument is a list of non-zero length, <code>drop-right</code> is guaranteed to + return a freshly-allocated list, even in the case where nothing is + dropped, <em>e.g.</em> <code>(drop-right lis 0)</code>. +- ++</p> ++</dd> + <!-- + ==== drop-right! + ==== take! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="take!"></a> +-<code class=proc-def>take!</code><var> x i -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">take!</code><var> x i -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="drop-right!"></a> +-<code class=proc-def>drop-right!</code><var> flist i -> list</var> +-<dd class=proc-def> ++<code class="proc-def">drop-right!</code><var> flist i -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>take!</code> and <code>drop-right!</code> are "linear-update" variants of <code>take</code> and + <code>drop-right</code>: the procedure is allowed, but not required, to alter the + argument list to produce the result. +-<p> ++</p><p> + If <var>x</var> is circular, <code>take!</code> may return a shorter-than-expected list: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (take! (circular-list 1 3 5) 8) => (1 3) + (take! (circular-list 1 3 5) 8) => (1 3 5 1 3 5 1 3) + </pre> +- ++</dd> + + <!-- +-==== split-at! ++==== split-at! + ==== split-at + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="split-at"></a> +-<code class=proc-def>split-at </code><var> x i -> [list object]</var> +-<dt class=proc-defn> ++<code class="proc-def">split-at </code><var> x i -> [list object]</var> ++</dt> ++<dt class="proc-defn"> + <a name="split-at!"></a> +-<code class=proc-def>split-at!</code><var> x i -> [list object]</var> +-<dd class=proc-def> +- <code>split-at</code> splits the list <var>x</var> +- at index <var>i</var>, returning a list of the ++<code class="proc-def">split-at!</code><var> x i -> [list object]</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <code>split-at</code> splits the list <var>x</var> ++ at index <var>i</var>, returning a list of the + first <var>i</var> elements, and the remaining tail. It is equivalent + to +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (values (take x i) (drop x i)) + </pre> ++<p> + <code>split-at!</code> is the linear-update variant. It is allowed, but not + required, to alter the argument list to produce the result. +-<pre class=code-example> +-(split-at '(a b c d e f g h) 3) => ++</p> ++<pre class="code-example"> ++(split-at '(a b c d e f g h) 3) => + (a b c) + (d e f g h) + </pre> +- ++</dd> + + <!-- + ==== last-pair + ==== last + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="last"></a> +-<code class=proc-def>last</code><var> pair -> object</var> +-<dt class=proc-defn> ++<code class="proc-def">last</code><var> pair -> object</var> ++</dt> ++<dt class="proc-defn"> + <a name="last-pair"></a> +-<code class=proc-def>last-pair</code><var> pair -> pair</var> +-<dd class=proc-def> +- <code>last</code> returns the last element of the non-empty, ++<code class="proc-def">last-pair</code><var> pair -> pair</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <code>last</code> returns the last element of the non-empty, + finite list <var>pair</var>. + <code>last-pair</code> returns the last pair in the non-empty, + finite list <var>pair</var>. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (last '(a b c)) => c + (last-pair '(a b c)) => (c) + </pre> +- ++</dd> + </dl> + + <!--========================================================================--> +@@ -1313,174 +1469,208 @@ partition the entire universe of Scheme values. + ==== length+ + ==== length + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="length"></a> +-<code class=proc-def>length </code><var>list -> integer</var> +-<dt class=proc-defn> ++<code class="proc-def">length </code><var>list -> integer</var> ++</dt> ++<dt class="proc-defn"> + <a name="length+"></a> +-<code class=proc-def>length+ </code><var>clist -> integer or #f</var> +-<dd class=proc-def> ++<code class="proc-def">length+ </code><var>clist -> integer or #f</var> ++</dt> ++<dd class="proc-def"> ++<p> + Both <code>length</code> and <code>length+</code> return the length of the argument. + It is an error to pass a value to <code>length</code> which is not a proper + list (finite and nil-terminated). In particular, this means an + implementation may diverge or signal an error when <code>length</code> is + applied to a circular list. +-<p> ++</p> ++<p> + <code>length+</code>, on the other hand, returns <code>#F</code> when applied to a circular + list. +-<p> +- The length of a proper list is a non-negative integer <var>n</var> such that <code>cdr</code> ++</p> ++<p> ++ The length of a proper list is a non-negative integer <var>n</var> such that <code>cdr</code> + applied <var>n</var> times to the list produces the empty list. +- ++</p> ++</dd> + + <!-- + ==== append append! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="append"></a> +-<code class=proc-def>append </code><var> list<sub>1</sub> ... -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">append </code><var> list<sub>1</sub> ... -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="append!"></a> +-<code class=proc-def>append!</code><var> list<sub>1</sub> ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">append!</code><var> list<sub>1</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] +- <code>append</code> returns a list consisting of the elements ++ <code>append</code> returns a list consisting of the elements + of <var>list<sub>1</sub></var> + followed by the elements of the other list parameters. +-<pre class=code-example> +-(append '(x) '(y)) => (x y) +-(append '(a) '(b c d)) => (a b c d) +-(append '(a (b)) '((c))) => (a (b) (c)) ++</p> ++<pre class="code-example"> ++(append '(x) '(y)) => (x y) ++(append '(a) '(b c d)) => (a b c d) ++(append '(a (b)) '((c))) => (a (b) (c)) + </pre> ++<p> + The resulting list is always newly allocated, except that it +- shares structure with the final <var>list<sub>i</sub></var> argument. +- This last argument may be any value at all; ++ shares structure with the final <var>list<sub>i</sub></var> argument. ++ This last argument may be any value at all; + an improper list results if it is not + a proper list. All other arguments must be proper lists. +-<pre class=code-example> +-(append '(a b) '(c . d)) => (a b c . d) +-(append '() 'a) => a +-(append '(x y)) => (x y) +-(append) => () ++</p> ++<pre class="code-example"> ++(append '(a b) '(c . d)) => (a b c . d) ++(append '() 'a) => a ++(append '(x y)) => (x y) ++(append) => () + </pre> +- ++<p> + <code>append!</code> is the "linear-update" variant of <code>append</code> + -- it is allowed, but not required, to alter cons cells in the argument +- lists to construct the result list. ++ lists to construct the result list. + The last argument is never altered; the result + list shares structure with this parameter. +- ++</p> ++</dd> + <!-- + ==== concatenate concatenate! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="concatenate"></a> +-<code class=proc-def>concatenate </code><var> list-of-lists -> value</var> +-<dt class=proc-defn> ++<code class="proc-def">concatenate </code><var> list-of-lists -> value</var> ++</dt> ++<dt class="proc-defn"> + <a name="concatenate!"></a> +-<code class=proc-def>concatenate!</code><var> list-of-lists -> value</var> +-<dd class=proc-def> ++<code class="proc-def">concatenate!</code><var> list-of-lists -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + These functions append the elements of their argument together. + That is, <code>concatenate</code> returns +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (apply append list-of-lists) + </pre> ++<p> + or, equivalently, +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (reduce-right append '() list-of-lists) + </pre> +- ++<p> + <code>concatenate!</code> is the linear-update variant, defined in + terms of <code>append!</code> instead of <code>append</code>. +- ++</p> + <p> + Note that some Scheme implementations do not support passing more than a +- certain number (<em>e.g.</em>, 64) of arguments to an n-ary procedure. ++ certain number (<em>e.g.</em>, 64) of arguments to an n-ary procedure. + In these implementations, the <code>(apply append ...)</code> idiom +- would fail when applied to long lists, ++ would fail when applied to long lists, + but <code>concatenate</code> would continue to function properly. +- ++</p> + <p> +- As with <code>append</code> and <code>append!</code>, ++ As with <code>append</code> and <code>append!</code>, + the last element of the input list may be any value at all. +- ++</p> ++</dd> + <!-- + ==== reverse reverse! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="reverse"></a> +-<code class=proc-def>reverse </code><var> list -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">reverse </code><var> list -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="reverse!"></a> +-<code class=proc-def>reverse!</code><var> list -> list</var> +-<dd class=proc-def> ++<code class="proc-def">reverse!</code><var> list -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + + <code>reverse</code> returns a newly allocated list consisting of + the elements of <var>list</var> in reverse order. +-<pre class=code-example> +-(reverse '(a b c)) => (c b a) ++</p> ++<pre class="code-example"> ++(reverse '(a b c)) => (c b a) + (reverse '(a (b c) d (e (f)))) +- => ((e (f)) d (b c) a) ++ => ((e (f)) d (b c) a) + </pre> ++<p> + <code>reverse!</code> is the linear-update variant of <code>reverse</code>. +- It is permitted, but not required, to alter the argument's cons cells ++ It is permitted, but not required, to alter the argument's cons cells + to produce the reversed list. +- ++</p> ++</dd> + + <!-- + ==== append-reverse! + ==== append-reverse + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="append-reverse"></a> +-<code class=proc-def>append-reverse </code><var>rev-head tail -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">append-reverse </code><var>rev-head tail -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="append-reverse!"></a> +-<code class=proc-def>append-reverse! </code><var>rev-head tail -> list</var> +-<dd class=proc-def> ++<code class="proc-def">append-reverse! </code><var>rev-head tail -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>append-reverse</code> returns + <code>(append (reverse <var>rev-head</var>) <var>tail</var>)</code>. + It is provided because it is a common operation -- a common + list-processing style calls for this exact operation to transfer values + accumulated in reverse order onto the front of another list, and because + the implementation is significantly more efficient than the simple +- composition it replaces. (But note that this pattern of iterative +- computation followed by a reverse can frequently be rewritten as a +- recursion, dispensing with the <code>reverse</code> and <code>append-reverse</code> steps, and +- shifting temporary, intermediate storage from the heap to the stack, +- which is typically a win for reasons of cache locality and eager storage ++ composition it replaces. (But note that this pattern of iterative ++ computation followed by a reverse can frequently be rewritten as a ++ recursion, dispensing with the <code>reverse</code> and <code>append-reverse</code> steps, and ++ shifting temporary, intermediate storage from the heap to the stack, ++ which is typically a win for reasons of cache locality and eager storage + reclamation.) ++</p> + <p> + <code>append-reverse!</code> is just the linear-update variant -- it is allowed, but + not required, to alter <var>rev-head</var>'s cons cells to construct the result. +- ++</p> ++</dd> + <!-- + ==== zip + ============================================================================--> +-<a name="zip"></a> +-<dt class=proc-def><code class=proc-def>zip</code> <var>clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> +-<dd class=proc-def> ++<dt class="proc-def" id="zip"><code class="proc-def">zip</code> <var>clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> + <pre>(lambda lists (apply map list lists)) + </pre> ++<p> + If <code>zip</code> is passed <var>n</var> lists, it returns a list as long as the shortest + of these lists, each element of which is an <var>n</var>-element list comprised + of the corresponding elements from the parameter lists. +- +-<pre class=code-example> +-(zip '(one two three) ++</p> ++<pre class="code-example"> ++(zip '(one two three) + '(1 2 3) + '(odd even odd even odd even odd even)) + => ((one 1 odd) (two 2 even) (three 3 odd)) + + (zip '(1 2 3)) => ((1) (2) (3)) + </pre> ++<p> + At least one of the argument lists must be finite: +-<pre class=code-example> +-(zip '(3 1 4 1) (circular-list #f #t)) +- => ((3 #f) (1 #t) (4 #f) (1 #t)) ++</p> ++<pre class="code-example"> ++(zip '(3 1 4 1) (circular-list #f #t)) ++ => ((3 #f) (1 #t) (4 #f) (1 #t)) + </pre> +- ++</dd> + <!-- + ==== unzip5 + ==== unzip4 +@@ -1488,83 +1678,96 @@ partition the entire universe of Scheme values. + ==== unzip2 + ==== unzip1 + ============================================================================--> +-<a name="unzip1"></a> +-<dt class=proc-def1> <code class=proc-def>unzip1</code><var> list -> list</var> +-<a name="unzip2"></a> +-<dt class=proc-defi> <code class=proc-def>unzip2</code><var> list -> [list list]</var> +-<a name="unzip3"></a> +-<dt class=proc-defi> <code class=proc-def>unzip3</code><var> list -> [list list list]</var> +-<a name="unzip4"></a> +-<dt class=proc-defi> <code class=proc-def>unzip4</code><var> list -> [list list list list]</var> +-<a name="unzip5"></a> +-<dt class=proc-defn> <code class=proc-def>unzip5</code><var> list -> [list list list list list]</var> +-<dd class=proc-def> +- <code>unzip1</code> takes a list of lists, +- where every list must contain at least one element, +- and returns a list containing the initial element of each such list. +- That is, it returns <code>(map car lists)</code>. ++<dt class="proc-def1" id="unzip1"> <code class="proc-def">unzip1</code><var> list -> list</var> ++</dt> ++<dt class="proc-defi" id="unzip2"> <code class="proc-def">unzip2</code><var> list -> [list list]</var> ++</dt> ++<dt class="proc-defi" id="unzip3"> <code class="proc-def">unzip3</code><var> list -> [list list list]</var> ++</dt> ++<dt class="proc-defi" id="unzip4"> <code class="proc-def">unzip4</code><var> list -> [list list list list]</var> ++</dt> ++<dt class="proc-defn" id="unzip5"> <code class="proc-def">unzip5</code><var> list -> [list list list list list]</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <code>unzip1</code> takes a list of lists, ++ where every list must contain at least one element, ++ and returns a list containing the initial element of each such list. ++ That is, it returns <code>(map car lists)</code>. + <code>unzip2</code> takes a list of lists, where every list must contain at least + two elements, and returns two values: a list of the first elements, + and a list of the second elements. <code>unzip3</code> does the same for the first + three elements of the lists, and so forth. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (unzip2 '((1 one) (2 two) (3 three))) => +- (1 2 3) ++ (1 2 3) + (one two three) + </pre> +- ++</dd> + <!-- + ==== count + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="count"></a> +-<code class=proc-def>count</code><var> pred clist<sub>1</sub> clist<sub>2</sub> -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">count</code><var> pred clist<sub>1</sub> clist<sub>2</sub> -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + <var>pred</var> is a procedure taking as many arguments as there +- are lists and returning a single value. It is applied ++ are lists and returning a single value. It is applied + element-wise to the elements of the <var>list</var>s, and a count is + tallied of the number of elements that produce a true value. This count + is returned. <code>count</code> is "iterative" in that it is guaranteed + to apply <var>pred</var> to the <var>list</var> elements in a + left-to-right order. + The counting stops when the shortest list expires. +-<pre class=code-example> +-(count even? '(3 1 4 1 5 9 2 5 6)) => 3 +-(count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)) => 3 ++</p> ++<pre class="code-example"> ++(count even? '(3 1 4 1 5 9 2 5 6)) => 3 ++(count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)) => 3 + </pre> ++<p> + At least one of the argument lists must be finite: +-<pre class=code-example> +-(count < '(3 1 4 1) (circular-list 1 10)) => 2 ++</p> ++<pre class="code-example"> ++(count < '(3 1 4 1) (circular-list 1 10)) => 2 + </pre> +- ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="FoldUnfoldMap">Fold, unfold & map</a></h2> ++<h2 id="FoldUnfoldMap">Fold, unfold & map</h2> + <dl> + <!-- + ==== fold + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="fold"></a> +-<code class=proc-def>fold</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> +- The fundamental list iterator. ++<code class="proc-def">fold</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ The fundamental list iterator. ++</p> + <p> + First, consider the single list-parameter case. If <var>clist<sub>1</sub></var> = (<var>e<sub>1</sub></var> <var>e<sub>2</sub></var> ... <var>e<sub>n</sub></var>), + then this procedure returns +-<div class=indent> ++</p> ++<div class="indent"> + <code>(<var>kons</var> <var>e<sub>n</sub></var> ... (<var>kons</var> <var>e<sub>2</sub></var> (<var>kons</var> <var>e<sub>1</sub></var> <var>knil</var>)) ... )</code> + </div> ++<p> + That is, it obeys the (tail) recursion +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold <var>kons</var> <var>knil</var> <var>lis</var>) = (fold <var>kons</var> (<var>kons</var> (car <var>lis</var>) <var>knil</var>) (cdr <var>lis</var>)) + (fold <var>kons</var> <var>knil</var> '()) = <var>knil</var> + </pre> +- ++<p> + Examples: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold + 0 lis) ; Add up the elements of LIS. + + (fold cons '() lis) ; Reverse LIS. +@@ -1581,297 +1784,357 @@ partition the entire universe of Scheme values. + 0 + lis) + </pre> +- ++<p> + If <var>n</var> list arguments are provided, then the <var>kons</var> function must take + <var>n</var>+1 parameters: one element from each list, and the "seed" or fold + state, which is initially <var>knil</var>. The fold operation terminates when + the shortest list runs out of values: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold cons* '() '(a b c) '(1 2 3 4 5)) => (c 3 b 2 a 1) + </pre> ++<p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== fold-right + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="fold-right"></a> +-<code class=proc-def>fold-right</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> +- The fundamental list recursion operator. ++<code class="proc-def">fold-right</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> + <p> +- First, consider the single list-parameter case. If <var>clist<sub>1</sub></var> = <code>(<var>e<sub>1</sub></var> <var>e<sub>2</sub></var> ... <var>e<sub>n</sub></var>)</code>, ++ The fundamental list recursion operator. ++</p> ++<p> ++ First, consider the single list-parameter case. If <var>clist<sub>1</sub></var> = <code>(<var>e<sub>1</sub></var> <var>e<sub>2</sub></var> ... <var>e<sub>n</sub></var>)</code>, + then this procedure returns +-<div class=indent><code> ++</p> ++<div class="indent"><code> + (<var>kons</var> <var>e<sub>1</sub></var> (<var>kons</var> <var>e<sub>2</sub></var> ... (<var>kons</var> <var>e<sub>n</sub></var> <var>knil</var>))) + </code></div> ++<p> + That is, it obeys the recursion +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold-right <var>kons</var> <var>knil</var> <var>lis</var>) = (<var>kons</var> (car <var>lis</var>) (fold-right <var>kons</var> <var>knil</var> (cdr <var>lis</var>))) + (fold-right <var>kons</var> <var>knil</var> '()) = <var>knil</var> + </pre> +- ++<p> + Examples: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold-right cons '() lis) ; Copy LIS. + + ;; Filter the even numbers out of LIS. + (fold-right (lambda (x l) (if (even? x) (cons x l) l)) '() lis)) + </pre> +- ++<p> + If <var>n</var> list arguments are provided, then the <var>kons</var> function must take + <var>n</var>+1 parameters: one element from each list, and the "seed" or fold + state, which is initially <var>knil</var>. The fold operation terminates when + the shortest list runs out of values: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (fold-right cons* '() '(a b c) '(1 2 3 4 5)) => (a 1 b 2 c 3) + </pre> ++<p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== pair-fold + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="pair-fold"></a> +-<code class=proc-def>pair-fold</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> +- Analogous to <code>fold</code>, but <var>kons</var> is applied to successive sublists of the ++<code class="proc-def">pair-fold</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Analogous to <code>fold</code>, but <var>kons</var> is applied to successive sublists of the + lists, rather than successive elements -- that is, <var>kons</var> is applied to the + pairs making up the lists, giving this (tail) recursion: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (pair-fold <var>kons</var> <var>knil</var> <var>lis</var>) = (let ((tail (cdr <var>lis</var>))) + (pair-fold <var>kons</var> (<var>kons</var> <var>lis</var> <var>knil</var>) tail)) + (pair-fold <var>kons</var> <var>knil</var> <code>'()</code>) = <var>knil</var> + </pre> ++<p> + For finite lists, the <var>kons</var> function may reliably apply + <code>set-cdr!</code> to the pairs it is given + without altering the sequence of execution. ++</p> + <p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;;; Destructively reverse a list. +-(pair-fold (lambda (pair tail) (set-cdr! pair tail) pair) '() lis)) ++(pair-fold (lambda (pair tail) (set-cdr! pair tail) pair) '() lis) + </pre> +- ++<p> + At least one of the list arguments must be finite. +- +- ++</p> ++</dd> + <!-- + ==== pair-fold-right + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="pair-fold-right"></a> +-<code class=proc-def>pair-fold-right</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> ++<code class="proc-def">pair-fold-right</code><var> kons knil clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + Holds the same relationship with <code>fold-right</code> that <code>pair-fold</code> holds with <code>fold</code>. + Obeys the recursion +-<pre class=code-example> +-(pair-fold-right <var>kons</var> <var>knil</var> <var>lis</var>) = ++</p> ++<pre class="code-example"> ++(pair-fold-right <var>kons</var> <var>knil</var> <var>lis</var>) = + (<var>kons</var> <var>lis</var> (pair-fold-right <var>kons</var> <var>knil</var> (cdr <var>lis</var>))) + (pair-fold-right <var>kons</var> <var>knil</var> <code>'()</code>) = <var>knil</var> + </pre> +- ++<p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (pair-fold-right cons '() '(a b c)) => ((a b c) (b c) (c)) + </pre> +- ++<p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== reduce + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="reduce"></a> +-<code class=proc-def>reduce</code><var> f ridentity list -> value</var> +-<dd class=proc-def> +- <code>reduce</code> is a variant of <code>fold</code>. ++<code class="proc-def">reduce</code><var> f ridentity list -> value</var> ++</dt> ++<dd class="proc-def"> + <p> +- <var>ridentity</var> should be a "right identity" of the procedure <var>f</var> -- that is, ++ <code>reduce</code> is a variant of <code>fold</code>. ++</p> ++<p> ++ <var>ridentity</var> should be a "right identity" of the procedure <var>f</var> -- that is, + for any value <var>x</var> acceptable to <var>f</var>, +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (<var>f</var> <var>x</var> <var>ridentity</var>) = <var>x</var> + </pre> +- ++<p> + <code>reduce</code> has the following definition: +-<div class=indent> +-If <var>list</var> = (), return <var>ridentity</var>;<br> ++</p> ++<div class="indent"> ++If <var>list</var> = (), return <var>ridentity</var>;<br /> + Otherwise, return <code>(fold <var>f</var> (car <var>list</var>) (cdr <var>list</var>))</code>. + </div> +- ...in other words, we compute ++<p> ++ ...in other words, we compute + <code>(fold <var>f</var> <var>ridentity</var> <var>list</var>)</code>. ++</p> + <p> + Note that <var>ridentity</var> is used <em>only</em> in the empty-list case. + You typically use <code>reduce</code> when applying <var>f</var> is expensive and you'd + like to avoid the extra application incurred when <code>fold</code> applies + <var>f</var> to the head of <var>list</var> and the identity value, +- redundantly producing the same value passed in to <var>f</var>. +- For example, if <var>f</var> involves searching a file directory or +- performing a database query, this can be significant. ++ redundantly producing the same value passed in to <var>f</var>. ++ For example, if <var>f</var> involves searching a file directory or ++ performing a database query, this can be significant. + In general, however, <code>fold</code> is useful in many contexts where <code>reduce</code> is not + (consider the examples given in the <code>fold</code> definition -- only one of the +- five folds uses a function with a right identity. ++ five folds uses a function with a right identity. + The other four may not be performed with <code>reduce</code>). +- ++</p> + <p> + Note: MIT Scheme and Haskell flip F's arg order for their <code>reduce</code> and + <code>fold</code> functions. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Take the max of a list of non-negative integers. + (reduce max 0 nums) ; i.e., (apply max 0 nums) + </pre> +- ++</dd> + <!-- + ==== reduce-right + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="reduce-right"></a> +-<code class=proc-def>reduce-right</code><var> f ridentity list -> value</var> +-<dd class=proc-def> ++<code class="proc-def">reduce-right</code><var> f ridentity list -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>reduce-right</code> is the fold-right variant of <code>reduce</code>. + It obeys the following definition: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (reduce-right <var>f</var> <var>ridentity</var> '()) = <var>ridentity</var> + (reduce-right <var>f</var> <var>ridentity</var> '(<var>e<sub>1</sub></var>)) = (<var>f</var> <var>e<sub>1</sub></var> <var>ridentity</var>) = <var>e<sub>1</sub></var> + (reduce-right <var>f</var> <var>ridentity</var> '(<var>e<sub>1</sub></var> <var>e<sub>2</sub></var> ...)) = + (<var>f</var> <var>e<sub>1</sub></var> (reduce <var>f</var> <var>ridentity</var> (<var>e<sub>2</sub></var> ...))) + </pre> +- ...in other words, we compute ++<p> ++ ...in other words, we compute + <code>(fold-right <var>f</var> <var>ridentity</var> <var>list</var>)</code>. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Append a bunch of lists together. + ;; I.e., (apply append list-of-lists) + (reduce-right append '() list-of-lists) + </pre> +- ++</dd> + <!-- + ==== unfold + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="unfold"></a> +-<code class=proc-def>unfold</code><var> p f g seed [tail-gen] -> list</var> +-<dd class=proc-def> ++<code class="proc-def">unfold</code><var> p f g seed [tail-gen] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>unfold</code> is best described by its basic recursion: +-<pre class=code-example> +-(unfold <var>p</var> <var>f</var> <var>g</var> <var>seed</var>) = ++</p> ++<pre class="code-example"> ++(unfold <var>p</var> <var>f</var> <var>g</var> <var>seed</var>) = + (if (<var>p</var> <var>seed</var>) (<var>tail-gen</var> <var>seed</var>) + (cons (<var>f</var> <var>seed</var>) + (unfold <var>p</var> <var>f</var> <var>g</var> (<var>g</var> <var>seed</var>)))) + </pre> + <dl> +-<dt> <var>p</var> <dd> Determines when to stop unfolding. +-<dt> <var>f</var> <dd> Maps each seed value to the corresponding list element. +-<dt> <var>g</var> <dd> Maps each seed value to next seed value. +-<dt> <var>seed</var> <dd> The "state" value for the unfold. +-<dt> <var>tail-gen</var> <dd> Creates the tail of the list; +- defaults to <code>(lambda (x) '())</code> ++ <dt> <var>p</var> </dt> ++ <dd> Determines when to stop unfolding.</dd> ++ <dt> <var>f</var> </dt> ++ <dd> Maps each seed value to the corresponding list element.</dd> ++ <dt> <var>g</var> </dt> ++ <dd> Maps each seed value to next seed value.</dd> ++ <dt> <var>seed</var> </dt> ++ <dd> The "state" value for the unfold.</dd> ++ <dt> <var>tail-gen</var> </dt> ++ <dd> Creates the tail of the list; defaults to <code>(lambda (x) '())</code></dd> + </dl> + <p> + In other words, we use <var>g</var> to generate a sequence of seed values +-<div class=indent> ++</p> ++<div class="indent"> + <var>seed</var>, <var>g</var>(<var>seed</var>), <var>g<sup>2</sup></var>(<var>seed</var>), <var>g<sup>3</sup></var>(<var>seed</var>), ... + </div> +- These seed values are mapped to list elements by <var>f</var>, +- producing the elements of the result list in a left-to-right order. ++<p> ++ These seed values are mapped to list elements by <var>f</var>, ++ producing the elements of the result list in a left-to-right order. + <var>P</var> says when to stop. +- ++</p> + <p> +- <code>unfold</code> is the fundamental recursive list constructor, +- just as <code>fold-right</code> is ++ <code>unfold</code> is the fundamental recursive list constructor, ++ just as <code>fold-right</code> is + the fundamental recursive list consumer. + While <code>unfold</code> may seem a bit abstract + to novice functional programmers, it can be used in a number of ways: +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; List of squares: 1^2 ... 10^2 + (unfold (lambda (x) (> x 10)) + (lambda (x) (* x x)) + (lambda (x) (+ x 1)) + 1) +- ++ + (unfold null-list? car cdr lis) ; Copy a proper list. + + ;; Read current input port into a list of values. + (unfold eof-object? values (lambda (x) (read)) (read)) + + ;; Copy a possibly non-proper list: +-(unfold not-pair? car cdr lis ++(unfold not-pair? car cdr lis + values) + + ;; Append HEAD onto TAIL: +-(unfold null-list? car cdr head ++(unfold null-list? car cdr head + (lambda (x) tail)) + </pre> +- +- Interested functional programmers may enjoy noting that ++<p> ++ Interested functional programmers may enjoy noting that + <code>fold-right</code> and <code>unfold</code> +- are in some sense inverses. +- That is, given operations <var>knull?</var>, <var>kar</var>, ++ are in some sense inverses. ++ That is, given operations <var>knull?</var>, <var>kar</var>, + <var>kdr</var>, <var>kons</var>, and <var>knil</var> satisfying +-<div class=indent> ++</p> ++<div class="indent"> + <code>(<var>kons</var> (<var>kar</var> <var>x</var>) (<var>kdr</var> <var>x</var>))</code> = <code>x</code> +- and ++ and + <code>(<var>knull?</var> <var>knil</var>)</code> = <code>#t</code> + </div> ++<p> + then +-<div class=indent> ++</p> ++<div class="indent"> + <code>(fold-right <var>kons</var> <var>knil</var> (unfold <var>knull?</var> <var>kar</var> <var>kdr</var> <var>x</var>))</code> = <var>x</var> + </div> ++<p> + and +-<div class=indent> ++</p> ++<div class="indent"> + <code>(unfold <var>knull?</var> <var>kar</var> <var>kdr</var> (fold-right <var>kons</var> <var>knil</var> <var>x</var>))</code> = <var>x</var>. + </div> +- ++<p> + This combinator sometimes is called an "anamorphism;" when an + explicit <var>tail-gen</var> procedure is supplied, it is called an + "apomorphism." +- +- ++</p> ++</dd> + <!-- + ==== unfold-right + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="unfold-right"></a> +-<code class=proc-def>unfold-right</code><var> p f g seed [tail] -> list</var> +-<dd class=proc-def> ++<code class="proc-def">unfold-right</code><var> p f g seed [tail] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>unfold-right</code> constructs a list with the following loop: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let lp ((seed seed) (lis tail)) + (if (p seed) lis + (lp (g seed) + (cons (f seed) lis)))) + </pre> + <dl> +-<dt> <var>p</var> <dd> Determines when to stop unfolding. +-<dt> <var>f</var> <dd> Maps each seed value to the corresponding list element. +-<dt> <var>g</var> <dd> Maps each seed value to next seed value. +-<dt> <var>seed</var> <dd> The "state" value for the unfold. +-<dt> <var>tail</var> <dd> list terminator; defaults to <code>'()</code>. ++ <dt> <var>p</var> </dt> ++ <dd> Determines when to stop unfolding.</dd> ++ <dt> <var>f</var> </dt> ++ <dd> Maps each seed value to the corresponding list element.</dd> ++ <dt> <var>g</var> </dt> ++ <dd> Maps each seed value to next seed value.</dd> ++ <dt> <var>seed</var> </dt> ++ <dd> The "state" value for the unfold.</dd> ++ <dt> <var>tail</var> </dt> ++ <dd> list terminator; defaults to <code>'()</code>.</dd> + </dl> + <p> + In other words, we use <var>g</var> to generate a sequence of seed values +-<div class=indent> ++</p> ++<div class="indent"> + <var>seed</var>, <var>g</var>(<var>seed</var>), <var>g<sup>2</sup></var>(<var>seed</var>), <var>g<sup>3</sup></var>(<var>seed</var>), ... + </div> +- These seed values are mapped to list elements by <var>f</var>, +- producing the elements of the result list in a right-to-left order. ++<p> ++ These seed values are mapped to list elements by <var>f</var>, ++ producing the elements of the result list in a right-to-left order. + <var>P</var> says when to stop. +- ++</p> + <p> +- <code>unfold-right</code> is the fundamental iterative list constructor, ++ <code>unfold-right</code> is the fundamental iterative list constructor, + just as <code>fold</code> is the +- fundamental iterative list consumer. ++ fundamental iterative list consumer. + While <code>unfold-right</code> may seem a bit abstract + to novice functional programmers, it can be used in a number of ways: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; List of squares: 1^2 ... 10^2 +-(unfold-right zero? ++(unfold-right zero? + (lambda (x) (* x x)) + (lambda (x) (- x 1)) + 10) +- ++ + ;; Reverse a proper list. + (unfold-right null-list? car cdr lis) + +@@ -1881,241 +2144,290 @@ Otherwise, return <code>(fold <var>f</var> (car <var>list</var>) (cdr <var>li + ;; (append-reverse rev-head tail) + (unfold-right null-list? car cdr rev-head tail) + </pre> +- +- Interested functional programmers may enjoy noting that ++<p> ++ Interested functional programmers may enjoy noting that + <code>fold</code> and <code>unfold-right</code> +- are in some sense inverses. +- That is, given operations <var>knull?</var>, <var>kar</var>, ++ are in some sense inverses. ++ That is, given operations <var>knull?</var>, <var>kar</var>, + <var>kdr</var>, <var>kons</var>, and <var>knil</var> satisfying +-<div class=indent> ++</p> ++<div class="indent"> + <code>(<var>kons</var> (<var>kar</var> <var>x</var>) (<var>kdr</var> <var>x</var>))</code> = <code>x</code> +- and ++ and + <code>(<var>knull?</var> <var>knil</var>)</code> = <code>#t</code> + </div> ++<p> + then +-<div class=indent> ++</p> ++<div class="indent"> + <code>(fold <var>kons</var> <var>knil</var> (unfold-right <var>knull?</var> <var>kar</var> <var>kdr</var> <var>x</var>))</code> = <var>x</var> + </div> ++<p> + and +-<div class=indent> ++</p> ++<div class="indent"> + <code>(unfold-right <var>knull?</var> <var>kar</var> <var>kdr</var> (fold <var>kons</var> <var>knil</var> <var>x</var>))</code> = <var>x</var>. + </div> +- ++<p> + This combinator presumably has some pretentious mathematical name; + interested readers are invited to communicate it to the author. +- ++</p> ++</dd> + <!-- + ==== map + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="map"></a> +-<code class=proc-def>map</code><var> proc clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> +-<dd class=proc-def> +- [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] +- +- <var>proc</var> is a procedure taking as many arguments +- as there are list arguments and returning a single value. ++<code class="proc-def">map</code><var> proc clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] ++ <var>proc</var> is a procedure taking as many arguments ++ as there are list arguments and returning a single value. + <code>map</code> applies <var>proc</var> element-wise to the elements +- of the lists and returns a list of the results, +- in order. +- The dynamic order in which <var>proc</var> ++ of the lists and returns a list of the results, ++ in order. ++ The dynamic order in which <var>proc</var> + is applied to the elements of the lists is unspecified. +- +-<pre class=code-example> +-(map cadr '((a b) (d e) (g h))) => (b e h) ++</p> ++<pre class="code-example"> ++(map cadr '((a b) (d e) (g h))) => (b e h) + + (map (lambda (n) (expt n n)) + '(1 2 3 4 5)) +- => (1 4 27 256 3125) ++ => (1 4 27 256 3125) + +-(map + '(1 2 3) '(4 5 6)) => (5 7 9) ++(map + '(1 2 3) '(4 5 6)) => (5 7 9) + + (let ((count 0)) + (map (lambda (ignored) + (set! count (+ count 1)) + count) +- '(a b))) => (1 2) <em>or</em> (2 1) ++ '(a b))) => (1 2) <em>or</em> (2 1) + </pre> +- +- This procedure is extended from its ++<p> ++ This procedure is extended from its + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> +- specification to allow the arguments to be of unequal length; +- it terminates when the shortest list runs out. ++ specification to allow the arguments to be of unequal length; ++ it terminates when the shortest list runs out. ++</p> + <p> + At least one of the argument lists must be finite: +-<pre class=code-example> +-(map + '(3 1 4 1) (circular-list 1 0)) => (4 1 5 1) ++</p> ++<pre class="code-example"> ++(map + '(3 1 4 1) (circular-list 1 0)) => (4 1 5 1) + </pre> +- ++</dd> + <!-- + ==== for-each + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="for-each"></a> +-<code class=proc-def>for-each</code><var> proc clist<sub>1</sub> clist<sub>2</sub> ... -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">for-each</code><var> proc clist<sub>1</sub> clist<sub>2</sub> ... -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] +- +- The arguments to <code>for-each</code> are like the arguments to ++</p> ++<p> ++ The arguments to <code>for-each</code> are like the arguments to + <code>map</code>, but + <code>for-each</code> calls <var>proc</var> for its side effects rather +- than for its values. +- Unlike <code>map</code>, <code>for-each</code> is guaranteed to call ++ than for its values. ++ Unlike <code>map</code>, <code>for-each</code> is guaranteed to call + <var>proc</var> on the elements of the lists in order from the first +- element(s) to the last, ++ element(s) to the last, + and the value returned by <code>for-each</code> is unspecified. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let ((v (make-vector 5))) + (for-each (lambda (i) + (vector-set! v i (* i i))) + '(0 1 2 3 4)) +- v) => #(0 1 4 9 16) ++ v) => #(0 1 4 9 16) + </pre> +- ++<p> + This procedure is extended from its + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> +- specification to allow the arguments to be of unequal length; +- it terminates when the shortest list runs out. ++ specification to allow the arguments to be of unequal length; ++ it terminates when the shortest list runs out. ++</p> + <p> + At least one of the argument lists must be finite. +- ++</p> ++</dd> + <!-- + ==== append-map! + ==== append-map + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="append-map"></a> +-<code class=proc-def>append-map </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dt class=proc-defn> ++<code class="proc-def">append-map </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dt class="proc-defn"> + <a name="append-map!"></a> +-<code class=proc-def>append-map! </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> +- Equivalent to +-<div class=indent><code> ++<code class="proc-def">append-map! </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Equivalent to ++</p> ++<div class="indent"><code> + (apply append (map <var>f</var> <var>clist<sub>1</sub></var> <var>clist<sub>2</sub></var> ...)) + </code></div> ++<p> + and +-<div class=indent><code> ++</p> ++<div class="indent"><code> + (apply append! (map <var>f</var> <var>clist<sub>1</sub></var> <var>clist<sub>2</sub></var> ...)) + </code></div> +- ++<p> + Map <var>f</var> over the elements of the lists, just as in the <code>map</code> function. + However, the results of the applications are appended together to + make the final result. <code>append-map</code> uses <code>append</code> to append the results + together; <code>append-map!</code> uses <code>append!</code>. ++</p> + <p> + The dynamic order in which the various applications of <var>f</var> are made is + not specified. ++</p> + <p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (append-map! (lambda (x) (list x (- x))) '(1 3 8)) + => (1 -1 3 -3 8 -8) + </pre> +- ++<p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== map! + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="map!"></a> +-<code class=proc-def>map!</code><var> f list<sub>1</sub> clist<sub>2</sub> ... -> list</var> +-<dd class=proc-def> +- Linear-update variant of <code>map</code> -- <code>map!</code> is allowed, but not required, to ++<code class="proc-def">map!</code><var> f list<sub>1</sub> clist<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Linear-update variant of <code>map</code> -- <code>map!</code> is allowed, but not required, to + alter the cons cells of <var>list<sub>1</sub></var> to construct the result list. ++</p> + <p> + The dynamic order in which the various applications of <var>f</var> are made is + not specified. +- ++</p> ++<p> + In the n-ary case, <var>clist<sub>2</sub></var>, <var>clist<sub>3</sub></var>, ... must have at least as many + elements as <var>list<sub>1</sub></var>. +- ++</p> ++</dd> + <!-- + ==== map-in-order + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="map-in-order"></a> +-<code class=proc-def>map-in-order </code><var>f</var> <var>clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">map-in-order </code><var>f</var> <var>clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + A variant of the <code>map</code> procedure that guarantees to apply <var>f</var> across + the elements of the <var>list<sub>i</sub></var> arguments in a left-to-right order. This + is useful for mapping procedures that both have side effects and + return useful values. ++</p> + <p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== pair-for-each + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="pair-for-each"></a> +-<code class=proc-def>pair-for-each </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> unspecific</var> +-<dd class=proc-def> ++<code class="proc-def">pair-for-each </code><var>f clist<sub>1</sub> clist<sub>2</sub> ... -> unspecific</var> ++</dt> ++<dd class="proc-def"> ++<p> + Like <code>for-each</code>, but <var>f</var> is applied to successive sublists of the argument + lists. That is, <var>f</var> is applied to the cons cells of the lists, rather + than the lists' elements. These applications occur in left-to-right + order. ++</p> + <p> + The <var>f</var> procedure may reliably apply <code>set-cdr!</code> to the pairs it is given + without altering the sequence of execution. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (pair-for-each (lambda (pair) (display pair) (newline)) '(a b c)) ==> + (a b c) + (b c) + (c) + </pre> +- ++<p> + At least one of the list arguments must be finite. +- ++</p> ++</dd> + <!-- + ==== filter-map + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="filter-map"></a> +-<code class=proc-def>filter-map</code><var> f clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">filter-map</code><var> f clist<sub>1</sub> clist<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Like <code>map</code>, but only true values are saved. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (filter-map (lambda (x) (and (number? x) (* x x))) '(a 1 b 3 c 7)) + => (1 9 49) + </pre> ++<p> + The dynamic order in which the various applications of <var>f</var> are made is + not specified. ++</p> + <p> + At least one of the list arguments must be finite. ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="FilteringPartitioning">Filtering & partitioning</a></h2> ++<h2 id="FilteringPartitioning">Filtering & partitioning</h2> + <dl> + + <!-- + ==== filter + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="filter"></a> +-<code class=proc-def>filter</code><var> pred list -> list</var> +-<dd class=proc-def> ++<code class="proc-def">filter</code><var> pred list -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return all the elements of <var>list</var> that satisfy predicate <var>pred</var>. + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The returned list may share a common tail with the argument list. + The dynamic order in which the various applications of <var>pred</var> are made is + not specified. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4) + </pre> +- ++</dd> + <!-- + ==== partition + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="partition"></a> +-<code class=proc-def>partition</code><var> pred list -> [list list]</var> +-<dd class=proc-def> ++<code class="proc-def">partition</code><var> pred list -> [list list]</var> ++</dt> ++<dd class="proc-def"> ++<p> + Partitions the elements of <var>list</var> with predicate <var>pred</var>, and returns two + values: the list of in-elements and the list of out-elements. + The list is not disordered -- elements occur in the result lists +@@ -2123,71 +2435,88 @@ Otherwise, return <code>(fold <var>f</var> (car <var>list</var>) (cdr <var>li + The dynamic order in which the various applications of <var>pred</var> are made is + not specified. One of the returned lists may share a common tail with the + argument list. +- +-<pre class=code-example> +-(partition symbol? '(one 2 3 four five 6)) => ++</p> ++<pre class="code-example"> ++(partition symbol? '(one 2 3 four five 6)) => + (one four five) + (2 3 6) + </pre> +- ++</dd> + <!-- + ==== remove + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="remove"></a> +-<code class=proc-def>remove</code><var> pred list -> list</var> +-<dd class=proc-def> ++<code class="proc-def">remove</code><var> pred list -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns <var>list</var> without the elements that satisfy predicate <var>pred</var>: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lambda (pred list) (filter (lambda (x) (not (pred x))) list)) + </pre> ++<p> + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The returned list may share a common tail with the argument list. +- The dynamic order in which the various applications of <var>pred</var> are made is ++ The dynamic order in which the various applications of <var>pred</var> are made is + not specified. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (remove even? '(0 7 8 8 43 -4)) => (7 43) + </pre> +- ++</dd> + <!-- + ==== remove! + ==== partition! + ==== filter! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="filter!"></a> +-<code class=proc-def>filter! </code><var>pred list -> list</var> +-<dt class=proc-defi> ++<code class="proc-def">filter! </code><var>pred list -> list</var> ++</dt> ++<dt class="proc-defi"> + <a name="partition!"></a> +-<code class=proc-def>partition! </code><var>pred list -> [list list]</var> +-<dt class=proc-defn> ++<code class="proc-def">partition! </code><var>pred list -> [list list]</var> ++</dt> ++<dt class="proc-defn"> + <a name="remove!"></a> +-<code class=proc-def>remove! </code><var>pred list -> list</var> +-<dd class=proc-def> ++<code class="proc-def">remove! </code><var>pred list -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Linear-update variants of <code>filter</code>, <code>partition</code> and <code>remove</code>. + These procedures are allowed, but not required, to alter the cons cells + in the argument list to construct the result lists. +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="Searching">Searching</a></h2> +-<p> ++<h2 id="Searching">Searching</h2> + ++<p> + The following procedures all search lists for a leftmost element satisfying + some criteria. This means they do not always examine the entire list; thus, + there is no efficient way for them to reliably detect and signal an error when + passed a dotted or circular list. Here are the general rules describing how + these procedures work when applied to different kinds of lists: ++</p> + + <dl> +- <dt> Proper lists: +- <dd> The standard, canonical behavior happens in this case. +- +- <dt> Dotted lists: +- <dd> It is an error to pass these procedures a dotted list ++ <dt> Proper lists: ++ </dt> ++ <dd> ++ <p> ++ The standard, canonical behavior happens in this case. ++ </p> ++ </dd> ++ <dt> Dotted lists: ++ </dt> ++ <dd> ++ <p> ++ It is an error to pass these procedures a dotted list + that does not contain an element satisfying the search + criteria. That is, it is an error if the procedure has + to search all the way to the end of the dotted list. +@@ -2200,23 +2529,31 @@ these procedures work when applied to different kinds of lists: + which is compliant with this <abbr title="Scheme Request for Implementation">SRFI</abbr> may not rely on any + particular behavior. Future <abbr title="Scheme Request for Implementation">SRFI</abbr>'s may refine SRFI-1 + to define specific behavior in this case. +- <p> ++ </p> ++ <p> + In brief, SRFI-1 compliant code may not pass a dotted + list argument to these procedures. +- +- <dt> Circular lists: +- <dd> It is an error to pass these procedures a circular list ++ </p> ++ </dd> ++ <dt> Circular lists: ++ </dt> ++ <dd> ++ <p> ++ It is an error to pass these procedures a circular list + that does not contain an element satisfying the search +- criteria. Note that the procedure is not required to ++ criteria. Note that the procedure is not required to + detect this case; it may simply diverge. It is, however, + acceptable to search a circular list <em>if the search is + successful</em> -- that is, if the list contains an element + satisfying the search criteria. ++ </p> ++ </dd> + </dl> + <p> + Here are some examples, using the <code>find</code> and <code>any</code> procedures as canonical + representatives: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Proper list -- success + (find even? '(1 2 3)) => 2 + (any even? '(1 2 3)) => #t +@@ -2230,7 +2567,7 @@ representatives: + (any even? '(1 3 . x)) => error + + ;; The dotted list contains an element satisfying the search. +-;; This case is not specified -- it could be success, an error, ++;; This case is not specified -- it could be success, an error, + ;; or some third possibility. + (find even? '(1 2 . x)) => error/undefined + (any even? '(1 2 . x)) => error/undefined ; success, error or other. +@@ -2248,17 +2585,19 @@ representatives: + <!-- + ==== find + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="find"></a> +-<code class=proc-def>find</code><var> pred clist -> value</var> +-<dd class=proc-def> ++<code class="proc-def">find</code><var> pred clist -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return the first element of <var>clist</var> that satisfies predicate <var>pred</var>; + false if no element does. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (find even? '(3 1 4 1 5 9)) => 4 + </pre> +- ++<p> + Note that <code>find</code> has an ambiguity in its lookup semantics -- if <code>find</code> + returns <code>#f</code>, you cannot tell (in general) if it found a <code>#f</code> element + that satisfied <var>pred</var>, or if it did not find any element at all. In +@@ -2267,145 +2606,168 @@ representatives: + guaranteed to have an element satisfying <var>pred</var>. However, in cases + where this ambiguity can arise, you should use <code>find-tail</code> instead of + <code>find</code> -- <code>find-tail</code> has no such ambiguity: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (cond ((find-tail pred lis) => (lambda (pair) ...)) ; Handle (CAR PAIR) + (else ...)) ; Search failed. + </pre> +- ++</dd> + <!-- + ==== find-tail + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="find-tail"></a> +-<code class=proc-def>find-tail</code><var> pred clist -> pair or false</var> +-<dd class=proc-def> ++<code class="proc-def">find-tail</code><var> pred clist -> pair or false</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return the first pair of <var>clist</var> whose car satisfies <var>pred</var>. If no pair does, + return false. ++</p> + <p> + <code>find-tail</code> can be viewed as a general-predicate variant of the <code>member</code> + function. ++</p> + <p> +- Examples: +-<pre class=code-example> ++ Examples: ++</p> ++<pre class="code-example"> + (find-tail even? '(3 1 37 -8 -5 0 0)) => (-8 -5 0 0) + (find-tail even? '(3 1 37 -5)) => #f + + ;; MEMBER X LIS: + (find-tail (lambda (elt) (equal? x elt)) lis) + </pre> +- ++<p> + In the circular-list case, this procedure "rotates" the list. +- ++</p> + <p> +- <code>Find-tail</code> is essentially <code>drop-while</code>, +- where the sense of the predicate is inverted: ++ <code>Find-tail</code> is essentially <code>drop-while</code>, ++ where the sense of the predicate is inverted: + <code>Find-tail</code> searches until it finds an element satisfying +- the predicate; <code>drop-while</code> searches until it finds an ++ the predicate; <code>drop-while</code> searches until it finds an + element that <em>doesn't</em> satisfy the predicate. +- ++</p> ++</dd> + <!-- + ==== take-while take-while! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="take-while"></a> +-<code class=proc-def>take-while </code><var> pred clist -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">take-while </code><var> pred clist -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="take-while!"></a> +-<code class=proc-def>take-while!</code><var> pred clist -> list</var> +-<dd class=proc-def> +- ++<code class="proc-def">take-while!</code><var> pred clist -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns the longest initial prefix of <var>clist</var> whose elements all + satisfy the predicate <var>pred</var>. +- ++</p> + <p> + <code>Take-while!</code> is the linear-update variant. It is allowed, but not + required, to alter the argument list to produce the result. +- +-<pre class=code-example> +-(take-while even? '(2 18 3 10 22 9)) => (2 18) ++</p> ++<pre class="code-example"> ++(take-while even? '(2 18 3 10 22 9)) => (2 18) + </pre> +- ++</dd> + <!-- + ==== drop-while + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="drop-while"></a> +-<code class=proc-def>drop-while</code><var> pred clist -> list</var> +-<dd class=proc-def> ++<code class="proc-def">drop-while</code><var> pred clist -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Drops the longest initial prefix of <var>clist</var> whose elements all + satisfy the predicate <var>pred</var>, and returns the rest of the list. +- +-<pre class=code-example> +-(drop-while even? '(2 18 3 10 22 9)) => (3 10 22 9) ++</p> ++<pre class="code-example"> ++(drop-while even? '(2 18 3 10 22 9)) => (3 10 22 9) + </pre> ++<p> + The circular-list case may be viewed as "rotating" the list. +- ++</p> ++</dd> + + <!-- + ==== span span! break break! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="span"></a> +-<code class=proc-def>span </code><var> pred clist -> [list clist]</var> +-<dt class=proc-defi> ++<code class="proc-def">span </code><var> pred clist -> [list clist]</var> ++</dt> ++<dt class="proc-defi"> + <a name="span!"></a> +-<code class=proc-def>span! </code><var> pred list -> [list list]</var> +-<dt class=proc-defi> ++<code class="proc-def">span! </code><var> pred list -> [list list]</var> ++</dt> ++<dt class="proc-defi"> + <a name="break"></a> +-<code class=proc-def>break </code><var> pred clist -> [list clist]</var> +-<dt class=proc-defn> ++<code class="proc-def">break </code><var> pred clist -> [list clist]</var> ++</dt> ++<dt class="proc-defn"> + <a name="break!"></a> +-<code class=proc-def>break!</code><var> pred list -> [list list]</var> +-<dd class=proc-def> +- ++<code class="proc-def">break!</code><var> pred list -> [list list]</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>Span</code> splits the list into the longest initial prefix whose +-elements all satisfy <var>pred</var>, and the remaining tail. +-<code>Break</code> inverts the sense of the predicate: ++elements all satisfy <var>pred</var>, and the remaining tail. ++<code>Break</code> inverts the sense of the predicate: + the tail commences with the first element of the input list + that satisfies the predicate. +- ++</p> + <p> +-In other words: +-<code>span</code> finds the initial span of elements +-satisfying <var>pred</var>, +-and <code>break</code> breaks the list at the first element satisfying ++In other words: ++<code>span</code> finds the intial span of elements ++satisfying <var>pred</var>, ++and <code>break</code> breaks the list at the first element satisfying + <var>pred</var>. +- ++</p> + <p> +-<code>Span</code> is equivalent to +-<pre class=code-example> +-(values (take-while <var>pred</var> <var>clist</var>) ++<code>Span</code> is equivalent to ++</p> ++<pre class="code-example"> ++(values (take-while <var>pred</var> <var>clist</var>) + (drop-while <var>pred</var> <var>clist</var>)) + </pre> +- + <p> +-<code>Span!</code> and <code>break!</code> are the linear-update variants. +-They are allowed, but not required, ++<code>Span!</code> and <code>break!</code> are the linear-update variants. ++They are allowed, but not required, + to alter the argument list to produce the result. +- +-<pre class=code-example> +-(span even? '(2 18 3 10 22 9)) => ++</p> ++<pre class="code-example"> ++(span even? '(2 18 3 10 22 9)) => + (2 18) + (3 10 22 9) + +-(break even? '(3 1 4 1 5 9)) => ++(break even? '(3 1 4 1 5 9)) => + (3 1) + (4 1 5 9) + </pre> +- ++</dd> + + <!-- + ==== any + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="any"></a> +-<code class=proc-def>any</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> ++<code class="proc-def">any</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + Applies the predicate across the lists, returning true if the predicate + returns true on any application. ++</p> + <p> + If there are <var>n</var> list arguments <var>clist<sub>1</sub></var> ... <var>clist<sub>n</sub></var>, then <var>pred</var> must be a +- procedure taking <var>n</var> arguments and returning a boolean result. ++ procedure taking <var>n</var> arguments ++ and returning a single value, interpreted as a boolean (that is, ++ <code>#f</code> means false, and any other value means true). ++</p> + <p> + <code>any</code> applies <var>pred</var> to the first elements of the <var>clist<sub>i</sub></var> parameters. + If this application returns a true value, <code>any</code> immediately returns +@@ -2413,37 +2775,45 @@ to alter the argument list to produce the result. + elements of the <var>clist<sub>i</sub></var> parameters, then the third, and so forth. + The iteration stops when a true value is produced or one of the lists runs + out of values; in +- the latter case, <code>any</code> returns <code>#f</code>. ++ the latter case, <code>any</code> returns <code>#f</code>. + The application of <var>pred</var> to the last element of the + lists is a tail call. ++</p> + <p> + Note the difference between <code>find</code> and <code>any</code> -- <code>find</code> returns the element + that satisfied the predicate; <code>any</code> returns the true value that the + predicate produced. ++</p> + <p> + Like <code>every</code>, <code>any</code>'s name does not end with a question mark -- this is to + indicate that it does not return a simple boolean (<code>#t</code> or <code>#f</code>), but a + general value. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (any integer? '(a 3 b 2.7)) => #t + (any integer? '(a 3.1 b 2.7)) => #f + (any < '(3 1 4 1 5) + '(2 7 1 8 2)) => #t + </pre> +- ++</dd> + <!-- + ==== every + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="every"></a> +-<code class=proc-def>every</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> +-<dd class=proc-def> ++<code class="proc-def">every</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + Applies the predicate across the lists, returning true if the predicate + returns true on every application. ++</p> + <p> + If there are <var>n</var> list arguments <var>clist<sub>1</sub></var> ... <var>clist<sub>n</sub></var>, then <var>pred</var> must be a +- procedure taking <var>n</var> arguments and returning a boolean result. ++ procedure taking <var>n</var> arguments ++ and returning a single value, interpreted as a boolean (that is, ++ <code>#f</code> means false, and any other value means true). ++</p> + <p> + <code>every</code> applies <var>pred</var> to the first elements of the <var>clist<sub>i</sub></var> parameters. + If this application returns false, <code>every</code> immediately returns false. +@@ -2451,27 +2821,36 @@ to alter the argument list to produce the result. + <var>clist<sub>i</sub></var> parameters, then the third, and so forth. The iteration stops + when a false value is produced or one of the lists runs out of values. + In the latter case, <code>every</code> returns +- the true value produced by its final application of <var>pred</var>. +- The application of <var>pred</var> to the last element of the lists ++ the true value produced by its final application of <var>pred</var>. ++ The application of <var>pred</var> to the last element of the lists + is a tail call. ++</p> + <p> + If one of the <var>clist<sub>i</sub></var> has no elements, <code>every</code> simply returns <code>#t</code>. ++</p> + <p> + Like <code>any</code>, <code>every</code>'s name does not end with a question mark -- this is to + indicate that it does not return a simple boolean (<code>#t</code> or <code>#f</code>), but a + general value. +- ++</p> ++</dd> + <!-- + ==== list-index + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="list-index"></a> +-<code class=proc-def>list-index</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> integer or false</var> +-<dd class=proc-def> ++<code class="proc-def">list-index</code><var> pred clist<sub>1</sub> clist<sub>2</sub> ... -> integer or false</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return the index of the leftmost element that satisfies <var>pred</var>. ++</p> + <p> + If there are <var>n</var> list arguments <var>clist<sub>1</sub></var> ... <var>clist<sub>n</sub></var>, then <var>pred</var> must be a +- function taking <var>n</var> arguments and returning a boolean result. ++ function taking <var>n</var> arguments ++ and returning a single value, interpreted as a boolean (that is, ++ <code>#f</code> means false, and any other value means true). ++</p> + <p> + <code>list-index</code> applies <var>pred</var> to the first elements of the <var>clist<sub>i</sub></var> parameters. + If this application returns true, <code>list-index</code> immediately returns zero. +@@ -2479,139 +2858,154 @@ to alter the argument list to produce the result. + <var>clist<sub>i</sub></var> parameters, then the third, and so forth. When it finds a tuple of + list elements that cause <var>pred</var> to return true, it stops and returns the + zero-based index of that position in the lists. ++</p> + <p> + The iteration stops when one of the lists runs out of values; in this + case, <code>list-index</code> returns <code>#f</code>. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (list-index even? '(3 1 4 1 5 9)) => 2 + (list-index < '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)) => 1 + (list-index = '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)) => #f + </pre> +- ++</dd> + <!-- + ==== member memq memv + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="member"></a> +-<code class=proc-def>member</code><var> x list [=] -> list</var> +-<dt class=proc-defi> ++<code class="proc-def">member</code><var> x list [=] -> list</var> ++</dt> ++<dt class="proc-defi"> + <a name="memq"></a> +-<code class=proc-def>memq</code><var> x list -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">memq</code><var> x list -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="memv"></a> +-<code class=proc-def>memv</code><var> x list -> list</var> +-<dd class=proc-def> +- [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] +- ++<code class="proc-def">memv</code><var> x list -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] + These procedures return the first sublist of <var>list</var> whose car is +- <var>x</var>, where the sublists of <var>list</var> are the +- non-empty lists returned by ++ <var>x</var>, where the sublists of <var>list</var> are the ++ non-empty lists returned by + <code>(drop <var>list</var> <var>i</var>)</code> +- for <var>i</var> less than the length of <var>list</var>. ++ for <var>i</var> less than the length of <var>list</var>. + If <var>x</var> does +- not occur in <var>list</var>, then <code>#f</code> is returned. ++ not occur in <var>list</var>, then <code>#f</code> is returned. + <code>memq</code> uses <code>eq?</code> to compare <var>x</var> +- with the elements of <var>list</var>, ++ with the elements of <var>list</var>, + while <code>memv</code> uses <code>eqv?</code>, and + <code>member</code> uses <code>equal?</code>. +- +-<pre class=code-example> +- (memq 'a '(a b c)) => (a b c) +- (memq 'b '(a b c)) => (b c) +- (memq 'a '(b c d)) => #f +- (memq (list 'a) '(b (a) c)) => #f ++</p> ++<pre class="code-example"> ++ (memq 'a '(a b c)) => (a b c) ++ (memq 'b '(a b c)) => (b c) ++ (memq 'a '(b c d)) => #f ++ (memq (list 'a) '(b (a) c)) => #f + (member (list 'a) +- '(b (a) c)) => ((a) c) +- (memq 101 '(100 101 102)) => *unspecified* +- (memv 101 '(100 101 102)) => (101 102) ++ '(b (a) c)) => ((a) c) ++ (memq 101 '(100 101 102)) => *unspecified* ++ (memv 101 '(100 101 102)) => (101 102) + </pre> +- +- <code>member</code> is extended from its ++<p> ++ <code>member</code> is extended from its + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + definition to allow the client to pass in +- an optional equality procedure <var>=</var> used to compare keys. ++ an optional equality procedure <var>=</var> used to compare keys. + ++</p> + <p> + The comparison procedure is used to compare the elements <var>e<sub>i</sub></var> of <var>list</var> + to the key <var>x</var> in this way: +-<div class=indent><code> ++</p> ++<div class="indent"><code> + (= <var>x</var> <var>e<sub>i</sub></var>) ; list is (E1 ... En) + </code></div> ++<p> + That is, the first argument is always <var>x</var>, and the second argument is + one of the list elements. Thus one can reliably find the first element + of <var>list</var> that is greater than five with + <code>(member 5 <var>list</var> <)</code> +- ++</p> + <p> + Note that fully general list searching may be performed with + the <code>find-tail</code> and <code>find</code> procedures, <em>e.g.</em> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (find-tail even? list) ; Find the first elt with an even key. + </pre> +- ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="Deletion">Deletion</a></h2> +-<p> ++<h2 id="Deletion">Deletion</h2> + + <dl> + <!-- + ==== delete! + ==== delete + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="delete"></a> +-<code class=proc-def>delete </code><var>x list [=] -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">delete </code><var>x list [=] -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="delete!"></a> +-<code class=proc-def>delete! </code><var>x list [=] -> list</var> +-<dd class=proc-def> ++<code class="proc-def">delete! </code><var>x list [=] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>delete</code> uses the comparison procedure =, which defaults to <code>equal?</code>, to find + all elements of <var>list</var> that are equal to <var>x</var>, and deletes them from <var>list</var>. The + dynamic order in which the various applications of <var>=</var> are made is not + specified. +- ++</p> + <p> + The list is not disordered -- elements that appear in the result list + occur in the same order as they occur in the argument list. + The result may share a common tail with the argument list. +- ++</p> + <p> + Note that fully general element deletion can be performed with the <code>remove</code> + and <code>remove!</code> procedures, <em>e.g.</em>: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Delete all the even elements from LIS: + (remove even? lis) + </pre> +- ++<p> + The comparison procedure is used in this way: + <code>(= <var>x</var> <var>e<sub>i</sub></var>)</code>. +- That is, <var>x</var> is always the first argument, ++ That is, <var>x</var> is always the first argument, + and a list element is always the + second argument. The comparison procedure will be used to compare each + element of <var>list</var> exactly once; the order in which it is applied to the + various <var>e<sub>i</sub></var> is not specified. Thus, one can reliably remove all the + numbers greater than five from a list with + <code>(delete 5 list <)</code> +- ++</p> + <p> + <code>delete!</code> is the linear-update variant of <code>delete</code>. + It is allowed, but not required, to alter the cons cells in +- its argument list to construct the result. +- ++ its argument list to construct the result. ++</p> ++</dd> + <!-- + ==== delete-duplicates! + ==== delete-duplicates + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="delete-duplicates"></a> +-<code class=proc-def>delete-duplicates </code><var>list [=] -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">delete-duplicates </code><var>list [=] -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="delete-duplicates!"></a> +-<code class=proc-def>delete-duplicates! </code><var>list [=] -> list</var> +-<dd class=proc-def> ++<code class="proc-def">delete-duplicates! </code><var>list [=] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>delete-duplicates</code> removes duplicate elements from the + list argument. + If there are multiple equal elements in the argument list, the result list +@@ -2619,19 +3013,22 @@ to alter the argument list to produce the result. + The order of these surviving elements is the same as in the original + list -- <code>delete-duplicates</code> does not disorder the list (hence it is useful + for "cleaning up" association lists). ++</p> + <p> + The <var>=</var> parameter is used to compare the elements of the list; it defaults +- to <code>equal?</code>. If <var>x</var> comes before <var>y</var> in <var>list</var>, then the comparison is performed ++ to <code>equal?</code>. If <var>x</var> comes before <var>y</var> in <var>list</var>, then the comparison is performed + <code>(= <var>x</var> <var>y</var>)</code>. +- The comparison procedure will be used to compare each pair of elements in +- <var>list</var> no more than once; ++ The comparison procedure will be used to compare each pair of elements in ++ <var>list</var> no more than once; + the order in which it is applied to the various pairs is not specified. ++</p> + <p> + Implementations of <code>delete-duplicates</code> + are allowed to share common tails + between argument and result lists -- for example, if the list argument + contains only unique elements, it may simply return exactly + this list. ++</p> + <p> + Be aware that, in general, <code>delete-duplicates</code> + runs in time O(n<sup>2</sup>) for <var>n</var>-element lists. +@@ -2639,12 +3036,13 @@ to alter the argument list to produce the result. + the list to bring equal elements together, then using a linear-time + algorithm to remove equal elements. Alternatively, one can use algorithms + based on element-marking, with linear-time results. +- ++</p> + <p> + <code>delete-duplicates!</code> is the linear-update variant of <code>delete-duplicates</code>; it + is allowed, but not required, to alter the cons cells in its argument + list to construct the result. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (delete-duplicates '(a b a c a b c z)) => (a b c z) + + ;; Clean up an alist: +@@ -2652,124 +3050,143 @@ to alter the argument list to produce the result. + (lambda (x y) (eq? (car x) (car y)))) + => ((a . 3) (b . 7) (c . 1)) + </pre> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="AssociationLists">Association lists</a></h2> ++<h2 id="AssociationLists">Association lists</h2> + <p> + An "association list" (or "alist") is a list of pairs. The car of each pair + contains a key value, and the cdr contains the associated data value. They can + be used to construct simple look-up tables in Scheme. Note that association + lists are probably inappropriate for performance-critical use on large data; + in these cases, hash tables or some other alternative should be employed. +- ++</p> + <dl> + <!-- + ==== assoc assq assv + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="assoc"></a> +-<code class=proc-def>assoc</code><var> key alist [=] -> pair or #f</var> +-<dt class=proc-defi> ++<code class="proc-def">assoc</code><var> key alist [=] -> pair or #f</var> ++</dt> ++<dt class="proc-defi"> + <a name="assq"></a> +-<code class=proc-def>assq</code><var> key alist -> pair or #f</var> +-<dt class=proc-defn> ++<code class="proc-def">assq</code><var> key alist -> pair or #f</var> ++</dt> ++<dt class="proc-defn"> + <a name="assv"></a> +-<code class=proc-def>assv</code><var> key alist -> pair or #f</var> +-<dd class=proc-def> +- +- [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] +- <var>alist</var> must be an association list -- a list of pairs. ++<code class="proc-def">assv</code><var> key alist -> pair or #f</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] ++ <var>alist</var> must be an association list -- a list of pairs. + These procedures +- find the first pair in <var>alist</var> whose car field is <var>key</var>, +- and returns that pair. +- If no pair in <var>alist</var> has <var>key</var> as its car, +- then <code>#f</code> is returned. +- <code>assq</code> uses <code>eq?</code> to compare <var>key</var> +- with the car fields of the pairs in <var>alist</var>, +- while <code>assv</code> uses <code>eqv?</code> ++ find the first pair in <var>alist</var> whose car field is <var>key</var>, ++ and returns that pair. ++ If no pair in <var>alist</var> has <var>key</var> as its car, ++ then <code>#f</code> is returned. ++ <code>assq</code> uses <code>eq?</code> to compare <var>key</var> ++ with the car fields of the pairs in <var>alist</var>, ++ while <code>assv</code> uses <code>eqv?</code> + and <code>assoc</code> uses <code>equal?</code>. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define e '((a 1) (b 2) (c 3))) +-(assq 'a e) => (a 1) +-(assq 'b e) => (b 2) +-(assq 'd e) => #f +-(assq (list 'a) '(((a)) ((b)) ((c)))) => #f +-(assoc (list 'a) '(((a)) ((b)) ((c)))) => ((a)) +-(assq 5 '((2 3) (5 7) (11 13))) => *unspecified* +-(assv 5 '((2 3) (5 7) (11 13))) => (5 7) ++(assq 'a e) => (a 1) ++(assq 'b e) => (b 2) ++(assq 'd e) => #f ++(assq (list 'a) '(((a)) ((b)) ((c)))) => #f ++(assoc (list 'a) '(((a)) ((b)) ((c)))) => ((a)) ++(assq 5 '((2 3) (5 7) (11 13))) => *unspecified* ++(assv 5 '((2 3) (5 7) (11 13))) => (5 7) + </pre> +- +- <code>assoc</code> is extended from its +- <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> ++<p> ++ <code>assoc</code> is extended from its ++ <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + definition to allow the client to pass in + an optional equality procedure <var>=</var> used to compare keys. +- ++</p> + <p> + The comparison procedure is used to compare the elements <var>e<sub>i</sub></var> of <var>list</var> + to the <var>key</var> parameter in this way: +-<div class=indent><code> ++</p> ++<div class="indent"><code> + (= <var>key</var> (car <var>e<sub>i</sub></var>)) ; list is (E1 ... En) + </code></div> +- That is, the first argument is always <var>key</var>, +- and the second argument is one of the list elements. ++<p> ++ That is, the first argument is always <var>key</var>, ++ and the second argument is one of the list elements. + Thus one can reliably find the first entry + of <var>alist</var> whose key is greater than five with + <code>(assoc 5 <var>alist</var> <)</code> +- ++</p> + <p> + Note that fully general alist searching may be performed with + the <code>find-tail</code> and <code>find</code> procedures, <em>e.g.</em> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Look up the first association in <var>alist</var> with an even key: + (find (lambda (a) (even? (car a))) alist) + </pre> +- ++</dd> + + <!-- + ==== alist-cons + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="alist-cons"></a> +-<code class=proc-def>alist-cons</code><var> key datum alist -> alist</var> +-<dd class=proc-def> ++<code class="proc-def">alist-cons</code><var> key datum alist -> alist</var> ++</dt> ++<dd class="proc-def"> + <pre> + (lambda (key datum alist) (cons (cons key datum) alist)) + </pre> ++<p> + Cons a new alist entry mapping <var>key</var> -> <var>datum</var> onto <var>alist</var>. +- ++</p> ++</dd> + <!-- + ==== alist-copy + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="alist-copy"></a> +-<code class=proc-def>alist-copy</code><var> alist -> alist</var> +-<dd class=proc-def> ++<code class="proc-def">alist-copy</code><var> alist -> alist</var> ++</dt> ++<dd class="proc-def"> ++<p> + Make a fresh copy of <var>alist</var>. This means copying each pair that + forms an association as well as the spine of the list, <em>i.e.</em> ++</p> + <pre> + (lambda (a) (map (lambda (elt) (cons (car elt) (cdr elt))) a)) + </pre> +- ++</dd> + <!-- + ==== alist-delete! + ==== alist-delete + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="alist-delete"></a> +-<code class=proc-def>alist-delete </code><var>key alist [=] -> alist</var> +-<dt class=proc-defn> ++<code class="proc-def">alist-delete </code><var>key alist [=] -> alist</var> ++</dt> ++<dt class="proc-defn"> + <a name="alist-delete!"></a> +-<code class=proc-def>alist-delete! </code><var>key alist [=] -> alist</var> +-<dd class=proc-def> +- <code>alist-delete</code> deletes all associations from <var>alist</var> with the given <var>key</var>, +- using key-comparison procedure =, which defaults to <code>equal?</code>. +- The dynamic order in which the various applications of <var>=</var> are made is not +- specified. ++<code class="proc-def">alist-delete! </code><var>key alist [=] -> alist</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <code>alist-delete</code> deletes all associations from <var>alist</var> with the given <var>key</var>, ++ using key-comparison procedure =, which defaults to <code>equal?</code>. ++ The dynamic order in which the various applications of <var>=</var> are made is not ++ specified. ++</p> + <p> + Return values may share common tails with the <var>alist</var> argument. + The alist is not disordered -- elements that appear in the result alist + occur in the same order as they occur in the argument alist. ++</p> + <p> + The comparison procedure is used to compare the element keys <var>k<sub>i</sub></var> of <var>alist</var>'s + entries to the <var>key</var> parameter in this way: +@@ -2777,366 +3194,427 @@ in these cases, hash tables or some other alternative should be employed. + Thus, one can reliably remove all entries of <var>alist</var> whose key is greater + than five with + <code>(alist-delete 5 <var>alist</var> <)</code> ++</p> + <p> + <code>alist-delete!</code> is the linear-update variant of <code>alist-delete</code>. + It is allowed, but not required, + to alter cons cells from the <var>alist</var> parameter to construct the result. +- ++</p> ++</dd> + </dl> + +- + <!--========================================================================--> +-<h2><a name="SetOperationsOnLists">Set operations on lists</a></h2> ++<h2 id="SetOperationsOnLists">Set operations on lists</h2> + <p> + These procedures implement operations on sets represented as lists of elements. +-They all take an <var>=</var> argument used to compare elements of lists. +-This equality procedure is required to be consistent with <code>eq?</code>. ++They all take an <var>=</var> argument used to compare elements of lists. ++This equality procedure is required to be consistent with <code>eq?</code>. + That is, it must be the case that +-<div class=indent> +- <code>(eq? <var>x</var> <var>y</var>)</code> => <code>(<var>=</var> <var>x</var> <var>y</var>)</code>. ++</p> ++<div class="indent"> ++ <code>(eq? <var>x</var> <var>y</var>)</code> => <code>(<var>=</var> <var>x</var> <var>y</var>)</code>. + </div> ++<p> + Note that this implies, in turn, that two lists that are <code>eq?</code> are + also set-equal by any legal comparison procedure. This allows for + constant-time determination of set operations on <code>eq?</code> lists. +- ++</p> + <p> +-Be aware that these procedures typically run in time +-O(<var>n</var> * <var>m</var>) +-for <var>n</var>- and <var>m</var>-element list arguments. ++Be aware that these procedures typically run in time ++O(<var>n</var> * <var>m</var>) ++for <var>n</var>- and <var>m</var>-element list arguments. + Performance-critical applications + operating upon large sets will probably wish to use other data + structures and algorithms. +- ++</p> + <dl> + <!-- + ==== lset<= + ============================================================================--> +-<dt class=proc-def> +-<a name="lset<="></a> +-<code class=proc-def>lset<=</code><var> = list<sub>1</sub> ... -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def"> ++<a name="lset<="></a> ++<code class="proc-def">lset<=</code><var> = list<sub>1</sub> ... -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns true iff every <var>list<sub>i</sub></var> is a subset of <var>list<sub>i+1</sub></var>, using <var>=</var> for +- the element-equality procedure. ++ the element-equality procedure. + List <var>A</var> is a subset of list <var>B</var> if every +- element in <var>A</var> is equal to some element of <var>B</var>. +- When performing an element comparison, ++ element in <var>A</var> is equal to some element of <var>B</var>. ++ When performing an element comparison, + the <var>=</var> procedure's first argument is an element + of <var>A</var>; its second, an element of <var>B</var>. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset<= eq? '(a) '(a b a) '(a b c c)) => #t + +-(lset<= eq?) => #t ; Trivial cases +-(lset<= eq? '(a)) => #t ++(lset<= eq?) => #t ; Trivial cases ++(lset<= eq? '(a)) => #t + </pre> +- ++</dd> + <!-- + ==== lset= + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset="></a> +-<code class=proc-def>lset=</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">lset=</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns true iff every <var>list<sub>i</sub></var> is set-equal to <var>list<sub>i+1</sub></var>, using <var>=</var> for + the element-equality procedure. "Set-equal" simply means that + <var>list<sub>i</sub></var> is a subset of <var>list<sub>i+1</sub></var>, and <var>list<sub>i+1</sub></var> is a subset of <var>list<sub>i</sub></var>. + The <var>=</var> procedure's first argument is an element of <var>list<sub>i</sub></var>; its second is an element of + <var>list<sub>i+1</sub></var>. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset= eq? '(b e a) '(a e b) '(e e b a)) => #t + +-(lset= eq?) => #t ; Trivial cases +-(lset= eq? '(a)) => #t ++(lset= eq?) => #t ; Trivial cases ++(lset= eq? '(a)) => #t + </pre> + ++<p id="lset=-element-equality-order"> ++<ins><em>Note added on 2020-06-02:</em> ++The reference (sample) <a href="#ReferencesLinks">implementation</a> ++had a bug that reversed the arguments to <var>=</var>. The ++implementation has been corrected to match the text above.</ins> ++</p> ++</dd> + <!-- + ==== lset-adjoin + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-adjoin"></a> +-<code class=proc-def>lset-adjoin</code><var> = list elt<sub>1</sub> ... -> list</var> +-<dd class=proc-def> +- Adds the <var>elt<sub>i</sub></var> elements not already in the list parameter to the ++<code class="proc-def">lset-adjoin</code><var> = list elt<sub>1</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Adds the <var>elt<sub>i</sub></var> elements not already in the list parameter to the + result list. The result shares a common tail with the list parameter. + The new elements are added to the front of the list, but no guarantees + are made about their order. The <var>=</var> parameter is an equality procedure +- used to determine if an <var>elt<sub>i</sub></var> is already a member of <var>list</var>. Its first ++ used to determine if an <var>elt<sub>i</sub></var> is already a member of <var>list</var>. Its first + argument is an element of <var>list</var>; its second is one of the <var>elt<sub>i</sub></var>. ++</p> + <p> + The list parameter is always a suffix of the result -- even if the list + parameter contains repeated elements, these are not reduced. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset-adjoin eq? '(a b c d c e) 'a 'e 'i 'o 'u) => (u o i a b c d c e) + </pre> +- ++</dd> + <!-- + ==== lset-union + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-union"></a> +-<code class=proc-def>lset-union</code><var> = list<sub>1</sub> ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">lset-union</code><var> = list<sub>1</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns the union of the lists, using <var>=</var> for the element-equality + procedure. ++</p> + <p> + The union of lists <var>A</var> and <var>B</var> is constructed as follows: ++</p> + <ul> +- <li> If <var>A</var> is the empty list, ++ <li> If <var>A</var> is the empty list, + the answer is <var>B</var> (or a copy of <var>B</var>). +- <li> Otherwise, the result is initialised to be list <var>A</var> ++ </li><li> Otherwise, the result is initialised to be list <var>A</var> + (or a copy of <var>A</var>). +- <li> Proceed through the elements of list <var>B</var> ++ </li><li> Proceed through the elements of list <var>B</var> + in a left-to-right order. +- If <var>b</var> is such an element of <var>B</var>, +- compare every element <var>r</var> of the current result list +- to <var>b</var>: +- <code>(= <var>r</var> <var>b</var>)</code>. +- If all comparisons fail, ++ If <var>b</var> is such an element of <var>B</var>, ++ compare every element <var>r</var> of the current result list ++ to <var>b</var>: ++ <code>(= <var>r</var> <var>b</var>)</code>. ++ If all comparisons fail, + <var>b</var> is consed onto the front of the result. +- </ul> ++ </li></ul> ++<p> + However, there is no guarantee that = will be applied to every pair +- of arguments from <var>A</var> and <var>B</var>. +- In particular, if <var>A</var> is <code>eq</code>? to <var>B</var>, ++ of arguments from <var>A</var> and <var>B</var>. ++ In particular, if <var>A</var> is <code>eq</code>? to <var>B</var>, + the operation may immediately terminate. +- ++</p> + <p> + In the n-ary case, the two-argument list-union operation is simply + folded across the argument lists. +- +-<pre class=code-example> +-(lset-union eq? '(a b c d e) '(a e i o u)) => ++</p> ++<pre class="code-example"> ++(lset-union eq? '(a b c d e) '(a e i o u)) => + (u o i a b c d e) + + ;; Repeated elements in LIST1 are preserved. +-(lset-union eq? '(a a c) '(x a x)) => (x a a c) ++(lset-union eq? '(a a c) '(x a x)) => (x a a c) + + ;; Trivial cases +-(lset-union eq?) => () +-(lset-union eq? '(a b c)) => (a b c) ++(lset-union eq?) => () ++(lset-union eq? '(a b c)) => (a b c) + </pre> +- ++</dd> + <!-- + ==== lset-intersection + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-intersection"></a> +-<code class=proc-def>lset-intersection</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> list</var> +-<dd class=proc-def> +- Returns the intersection of the lists, ++<code class="proc-def">lset-intersection</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Returns the intersection of the lists, + using <var>=</var> for the element-equality procedure. ++</p> + <p> + The intersection of lists <var>A</var> and <var>B</var> +- is comprised of every element of <var>A</var> that is <var>=</var> +- to some element of <var>B</var>: +- <code>(<var>=</var> <var>a</var> <var>b</var>)</code>, ++ is comprised of every element of <var>A</var> that is <var>=</var> ++ to some element of <var>B</var>: ++ <code>(<var>=</var> <var>a</var> <var>b</var>)</code>, + for <var>a</var> in <var>A</var>, and <var>b</var> in <var>B</var>. +- Note this implies that an element which appears in <var>B</var> ++ Note this implies that an element which appears in <var>B</var> + and multiple times in list <var>A</var> + will also appear multiple times in the result. ++</p> + <p> + The order in which elements appear in the result is the same as +- they appear in <var>list<sub>1</sub></var> -- +- that is, <code>lset-intersection</code> essentially filters +- <var>list<sub>1</sub></var>, +- without disarranging element order. ++ they appear in <var>list<sub>1</sub></var> -- ++ that is, <code>lset-intersection</code> essentially filters ++ <var>list<sub>1</sub></var>, ++ without disarranging element order. + The result may + share a common tail with <var>list<sub>1</sub></var>. ++</p> + <p> + In the n-ary case, the two-argument list-intersection operation is simply + folded across the argument lists. However, the dynamic order in which the +- applications of <var>=</var> are made is not specified. ++ applications of <var>=</var> are made is not specified. + The procedure may check an +- element of <var>list<sub>1</sub></var> for membership ++ element of <var>list<sub>1</sub></var> for membership + in every other list before proceeding to +- consider the next element of <var>list<sub>1</sub></var>, ++ consider the next element of <var>list<sub>1</sub></var>, + or it may completely intersect <var>list<sub>1</sub></var> +- and <var>list<sub>2</sub></var> +- before proceeding to <var>list<sub>3</sub></var>, ++ and <var>list<sub>2</sub></var> ++ before proceeding to <var>list<sub>3</sub></var>, + or it may go about its work in some third order. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset-intersection eq? '(a b c d e) '(a e i o u)) => (a e) + + ;; Repeated elements in LIST1 are preserved. +-(lset-intersection eq? '(a x y a) '(x a x z)) => '(a x a) ++(lset-intersection eq? '(a x y a) '(x a x z)) => '(a x a) + +-(lset-intersection eq? '(a b c)) => (a b c) ; Trivial case ++(lset-intersection eq? '(a b c)) => (a b c) ; Trivial case + </pre> +- ++</dd> + <!-- + ==== lset-difference + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-difference"></a> +-<code class=proc-def>lset-difference</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> list</var> +-<dd class=proc-def> ++<code class="proc-def">lset-difference</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns the difference of the lists, using <var>=</var> for the element-equality + procedure -- all the elements of <var>list<sub>1</sub></var> that are not + <var>=</var> to any element from one of the +- other <var>list<sub>i</sub></var> parameters. ++ other <var>list<sub>i</sub></var> parameters. ++</p> + <p> +- The <var>=</var> procedure's first argument is +- always an element of <var>list<sub>1</sub></var>; ++ The <var>=</var> procedure's first argument is ++ always an element of <var>list<sub>1</sub></var>; + its second is an element of one of the other <var>list<sub>i</sub></var>. +- Elements that are repeated multiple times in the +- <var>list<sub>1</sub></var> parameter +- will occur multiple times in the result. ++ Elements that are repeated multiple times in the ++ <var>list<sub>1</sub></var> parameter ++ will occur multiple times in the result. + + The order in which elements appear in the result is the same as +- they appear in <var>list<sub>1</sub></var> -- ++ they appear in <var>list<sub>1</sub></var> -- + that is, <code>lset-difference</code> essentially +- filters <var>list<sub>1</sub></var>, without disarranging element order. +- The result may share a common tail with <var>list<sub>1</sub></var>. ++ filters <var>list<sub>1</sub></var>, without disarranging element order. ++ The result may share a common tail with <var>list<sub>1</sub></var>. + + The dynamic order in which the applications of <var>=</var> are made is not +- specified. ++ specified. + The procedure may check an element of <var>list<sub>1</sub></var> + for membership in every other list before proceeding to consider the + next element of <var>list<sub>1</sub></var>, +- or it may completely compute the difference of ++ or it may completely compute the difference of + <var>list<sub>1</sub></var> and <var>list<sub>2</sub></var> before +- proceeding to <var>list<sub>3</sub></var>, ++ proceeding to <var>list<sub>3</sub></var>, + or it may go about its work in some third order. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset-difference eq? '(a b c d e) '(a e i o u)) => (b c d) + +-(lset-difference eq? '(a b c)) => (a b c) ; Trivial case ++(lset-difference eq? '(a b c)) => (a b c) ; Trivial case + </pre> +- ++</dd> + <!-- + ==== lset-xor + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-xor"></a> +-<code class=proc-def>lset-xor</code><var> = list<sub>1</sub> ... -> list</var> +-<dd class=proc-def> +- Returns the exclusive-or of the sets, +- using <var>=</var> for the element-equality procedure. ++<code class="proc-def">lset-xor</code><var> = list<sub>1</sub> ... -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ Returns the exclusive-or of the sets, ++ using <var>=</var> for the element-equality procedure. + If there are exactly two lists, this is all the elements + that appear in exactly one of the two lists. The operation is associative, + and thus extends to the n-ary case -- the elements that appear in an + odd number of the lists. The result may share a common tail with any of + the <var>list<sub>i</sub></var> parameters. ++</p> + <p> +- More precisely, for two lists <var>A</var> and <var>B</var>, ++ More precisely, for two lists <var>A</var> and <var>B</var>, + <var>A</var> xor <var>B</var> is a list of ++</p> + <ul> + <li> every element <var>a</var> of <var>A</var> + such that there is no element <var>b</var> of <var>B</var> + such that <code>(<var>=</var> <var>a</var> <var>b</var>)</code>, and +- <li> every element <var>b</var> of <var>B</var> ++ </li><li> every element <var>b</var> of <var>B</var> + such that there is no element <var>a</var> of <var>A</var> + such that <code>(<var>=</var> <var>b</var> <var>a</var>)</code>. +- </ul> ++ </li></ul> ++<p> + However, an implementation is allowed to assume that <var>=</var> is + symmetric -- that is, that +-<div class=indent> +- <code>(<var>=</var> <var>a</var> <var>b</var>)</code> => ++</p> ++<div class="indent"> ++ <code>(<var>=</var> <var>a</var> <var>b</var>)</code> => + <code>(<var>=</var> <var>b</var> <var>a</var>)</code>. + </div> +- This means, for example, that if a comparison ++<p> ++ This means, for example, that if a comparison + <code>(<var>=</var> <var>a</var> <var>b</var>)</code> produces +- true for some <var>a</var> in <var>A</var> ++ true for some <var>a</var> in <var>A</var> + and <var>b</var> in <var>B</var>, + both <var>a</var> and <var>b</var> may be removed from + inclusion in the result. ++</p> + <p> + In the n-ary case, the binary-xor operation is simply folded across + the lists. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (lset-xor eq? '(a b c d e) '(a e i o u)) => (d c b i o u) + + ;; Trivial cases. +-(lset-xor eq?) => () +-(lset-xor eq? '(a b c d e)) => (a b c d e) ++(lset-xor eq?) => () ++(lset-xor eq? '(a b c d e)) => (a b c d e) + </pre> +- ++</dd> + + <!-- + ==== lset-diff+intersection + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="lset-diff+intersection"></a> +-<code class=proc-def>lset-diff+intersection</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> [list list]</var> +-<dd class=proc-def> ++<code class="proc-def">lset-diff+intersection</code><var> = list<sub>1</sub> list<sub>2</sub> ... -> [list list]</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns two values -- the difference and the intersection of the lists. +- Is equivalent to +-<pre class=code-example> ++ Is equivalent to ++</p> ++<pre class="code-example"> + (values (lset-difference <var>=</var> <var>list<sub>1</sub></var> <var>list<sub>2</sub></var> ...) + (lset-intersection <var>=</var> <var>list<sub>1</sub></var> + (lset-union <var>=</var> <var>list<sub>2</sub></var> ...))) + </pre> ++<p> + but can be implemented more efficiently. ++</p> + <p> + The <var>=</var> procedure's first argument is an element of <var>list<sub>1</sub></var>; its second + is an element of one of the other <var>list<sub>i</sub></var>. ++</p> + <p> +- Either of the answer lists may share a ++ Either of the answer lists may share a + common tail with <var>list<sub>1</sub></var>. + This operation essentially partitions <var>list<sub>1</sub></var>. +- ++</p> ++</dd> + <!-- +-==== lset-diff+intersection! ++==== lset-diff+intersection! + ==== lset-xor! + ==== lset-difference! + ==== lset-intersection! + ==== lset-union! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="lset-union!"></a> +-<code class=proc-def>lset-union! </code><var>= list<sub>1</sub> ... -> list</var> +-<dt class=proc-defi> ++<code class="proc-def">lset-union! </code><var>= list<sub>1</sub> ... -> list</var> ++</dt> ++<dt class="proc-defi"> + <a name="lset-intersection!"></a> +-<code class=proc-def>lset-intersection! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> list</var> +-<dt class=proc-defi> ++<code class="proc-def">lset-intersection! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> list</var> ++</dt> ++<dt class="proc-defi"> + <a name="lset-difference!"></a> +-<code class=proc-def>lset-difference! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> list</var> +-<dt class=proc-defi> ++<code class="proc-def">lset-difference! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> list</var> ++</dt> ++<dt class="proc-defi"> + <a name="lset-xor!"></a> +-<code class=proc-def>lset-xor! </code><var>= list<sub>1</sub> ... -> list</var> +-<dt class=proc-defn> ++<code class="proc-def">lset-xor! </code><var>= list<sub>1</sub> ... -> list</var> ++</dt> ++<dt class="proc-defn"> + <a name="lset-diff+intersection!"></a> +-<code class=proc-def>lset-diff+intersection! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> [list list]</var> +-<dd class=proc-def> ++<code class="proc-def">lset-diff+intersection! </code><var>= list<sub>1</sub> list<sub>2</sub> ... -> [list list]</var> ++</dt> ++<dd class="proc-def"> ++<p> + These are linear-update variants. They are allowed, but not required, + to use the cons cells in their first list parameter to construct their +- answer. <code>lset-union!</code> is permitted to recycle cons cells from <em>any</em> ++ answer. <code>lset-union!</code> is permitted to recycle cons cells from <em>any</em> + of its list arguments. ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="PrimitiveSideEffects">Primitive side-effects</a></h2> ++<h2 id="PrimitiveSideEffects">Primitive side-effects</h2> + <p> +-These two procedures are the primitive, +-<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> ++These two procedures are the primitive, ++<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + side-effect operations on pairs. +- ++</p> + <dl> + <!-- + ==== set-car! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="set-car!"></a> +-<code class=proc-def>set-car!</code><var> pair object -> unspecified</var> +-<dt class=proc-defn> ++<code class="proc-def">set-car!</code><var> pair object -> unspecified</var> ++</dt> ++<dt class="proc-defn"> + <a name="set-cdr!"></a> +-<code class=proc-def>set-cdr!</code><var> pair object -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">set-cdr!</code><var> pair object -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + These procedures store <var>object</var> in the car and cdr field + of <var>pair</var>, respectively. + The value returned is unspecified. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (f) (list 'not-a-constant-list)) + (define (g) '(constant-list)) +-(set-car! (f) 3) => *unspecified* +-(set-car! (g) 3) => *error* ++(set-car! (f) 3) => *unspecified* ++(set-car! (g) 3) => *error* + </pre> ++</dd> + </dl> + + <!--========================================================================--> +-<h1><a name="Acknowledgements">Acknowledgements</a></h1> ++<h2 id="Acknowledgements">Acknowledgements</h2> + <p> + The design of this library benefited greatly from the feedback provided during + the <abbr title="Scheme Request for Implementation">SRFI</abbr> discussion phase. Among those contributing thoughtful commentary and +@@ -3149,77 +3627,80 @@ Kelsey, Donovan Kolbly, Shriram Krishnamurthi, Dave Mason, Jussi Piitulainen, + David Pokorny, Duncan Smith, Mike Sperber, Maciej Stachowiak, Harvey J. Stein, + John David Stone, and Joerg F. Wittenberger. I am grateful to them for their + assistance. ++</p> + <p> + I am also grateful the authors, implementors and documentors of all the systems + mentioned in the rationale. Aubrey Jaffer and Kent Pitman should be noted +-for their work in producing Web-accessible versions of the R5RS and ++for their work in producing Web-accessible versions of the R5RS and + <a href="#CommonLisp">Common Lisp</a> spec, which was a tremendous aid. ++</p> + <p> + This is not to imply that these individuals necessarily endorse the final +-results, of course. +- ++results, of course. ++</p> + + <!--========================================================================--> +-<h1><a name="ReferencesLinks">References & links</a></h1> +-<p> ++<h2 id="ReferencesLinks">References & links</h2> + + <dl> +-<dt class=biblio>This document, in HTML: +-<dd><a href="srfi-1.html"> +- http://srfi.schemers.org/srfi-1/srfi-1.html</a> ++<dt class="biblio">This document, in HTML: ++</dt><dd><a href=""> ++ https://srfi.schemers.org/srfi-1/srfi-1.html</a> + +-<dt class=biblio>Source code for the reference implementation: +-<dd><a HREF="http://srfi.schemers.org/srfi-1/srfi-1-reference.scm"> +- http://srfi.schemers.org/srfi-1/srfi-1-reference.scm</a> ++</dd><dt class="biblio">Source code for the reference implementation: ++</dt><dd><a href="https://srfi.schemers.org/srfi-1/srfi-1-reference.scm"> ++ https://srfi.schemers.org/srfi-1/srfi-1-reference.scm</a> + +-<dt class=biblio>Archive of SRFI-1 discussion-list email: +-<dd><a href="http://srfi.schemers.org/srfi-1/mail-archive/maillist.html"> +- http://srfi.schemers.org/srfi-1/mail-archive/maillist.html</a> ++</dd><dt class="biblio">Archive of SRFI-1 discussion-list email: ++</dt><dd><a href="https://srfi-email.schemers.org/srfi-1"> ++ https://srfi-email.schemers.org/srfi-1</a> ++ ++</dd><dt class="biblio">SRFI web site: ++</dt><dd><a href="https://srfi.schemers.org/"> ++ https://srfi.schemers.org/</a> ++</dd></dl> + +-<dt class=biblio>SRFI web site: +-<dd><a href="http://srfi.schemers.org/"> +- http://srfi.schemers.org/</a> +-</dl> + +-<p> + + <dl> +-<dt class=biblio><strong><a name="CommonLisp">[CommonLisp]</a></strong></dt> +-<dd><em>Common Lisp: the Language</em><br> +-Guy L. Steele Jr. (editor).<br> +-Digital Press, Maynard, Mass., second edition 1990.<br> +-Available at <a href="http://www.elwood.com/alu/table/references.htm#cltl2"> +-http://www.elwood.com/alu/table/references.htm#cltl2</a>. ++<dt class="biblio"><strong><a name="CommonLisp">[CommonLisp]</a></strong></dt> ++<dd> ++<p> ++<em>Common Lisp: the Language</em><br /> ++Guy L. Steele Jr. (editor).<br /> ++Digital Press, Maynard, Mass., second edition 1990.<br /> ++(<a href="https://en.wikipedia.org/wiki/Common_Lisp_the_Language">Wikipedia entry</a>) ++</p> + <p> +- + The Common Lisp "HyperSpec," produced by Kent Pitman, is essentially + the ANSI spec for Common Lisp: +-<a href="http://www.harlequin.com/education/books/HyperSpec/"> +-http://www.harlequin.com/education/books/HyperSpec/</a>. +- +-<dt class=biblio><strong><a name="R5RS">[R5RS]</a></strong></dt> +-<dd>Revised<sup>5</sup> report on the algorithmic language Scheme.<br> +- R. Kelsey, W. Clinger, J. Rees (editors). <br> +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br> +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br> ++<a href="http://www.lispworks.com/documentation/HyperSpec/Front/index.htm">http://www.lispworks.com/documentation/HyperSpec/Front/index.htm</a> ++</p> ++</dd> ++<dt class="biblio"><strong><a name="R5RS">[R5RS]</a></strong></dt> ++<dd>Revised<sup>5</sup> report on the algorithmic language Scheme.<br /> ++ R. Kelsey, W. Clinger, J. Rees (editors). <br /> ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br /> ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br /> + Available at <a href="http://www.schemers.org/Documents/Standards/"> + http://www.schemers.org/Documents/Standards/</a>. +- ++</dd> + </dl> + + + ++ + <!--========================================================================--> +-<h1><a name="Copyright">Copyright</a></h1> ++<h2 id="Copyright">Copyright</h2> + <p> +- + Certain portions of this document -- the specific, marked segments of text + describing the R5RS procedures -- were adapted with permission from the R5RS + report. ++</p> + <p> +- +-All other text is copyright (C) Olin Shivers (1998, 1999). +-All Rights Reserved. ++All other text is copyright (C) Olin Shivers (1998, 1999). ++All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -3242,5 +3723,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Michael Sperber</a></address> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html +index 987edd5..f100a02 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-11.html +@@ -1,55 +1,74 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-11 ┃ ++┃ Commit: 49867af77ba9c626ab420f45d88ee9ef3c0f6e13 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 11: Syntax for receiving multiple values</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 11: Syntax for receiving multiple values</h1> + +-SRFI 11: Syntax for receiving multiple values ++<p>by Lars T Hansen</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 11 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-11/srfi-11.html">https://srfi.schemers.org/srfi-11/srfi-11.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Lars T Hansen ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+11+at+srfi+dotschemers+dot+org">srfi-11@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-11">archive</a>.</p> ++<ul> ++<li>Received: 1999-09-10 ++</li><li>Draft: 1999-09-14--1999-11-12 ++</li><li>Revised: 1999-11-01 ++</li><li>Revised: 2000-03-15 ++</li><li>Final: 2000-03-15 ++</li></ul> + +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status +-that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-11/mail-archive/maillist.html">the archive of +-the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/09/10 +-<LI>Draft: 1999/09/14-1999/11/12 +-<LI>Revised: 1999/11/01 +-<LI>Revised: 2000/03/15 +-<LI>Final: 2000/03/15 +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + The SRFI introduces syntactic forms LET-VALUES and LET*-VALUES that bind the values of + expressions that return multiple values. + +-<H1>Issues</H1> ++<h2>Issues</h2> + + None. + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + LET-VALUES and LET*-VALUES reduce the clutter of the CALL-WITH-VALUES notation for + receiving multiple values. + + +-<H1>Specification</H1> ++<h2>Specification</h2> + + <dl> +-<dt><a name="let-values"></a> ++<dt id="let-values"> + <tt>(LET-VALUES ((<formals> <expression>) ...) <body>)</tt> +-<br>Syntax ++<br />Syntax ++</dt> + <dd> +-<p>Each <formals> should be a formal arguments list as for a LAMBDA ++<p>Each <formals> should be a formal arguments list as for a LAMBDA + expression, cf section 4.1.4 of the R5RS.</p> + + <p>The <expression>s are evaluated in the current environment, the +@@ -64,7 +83,6 @@ receiving multiple values. + error for an <expression> to return a number of values that does + not match its corresponding <formals>.</p> + +-<p> + <pre> + (let-values (((a b . c) (values 1 2 3 4))) + (list a b c)) --> (1 2 (3 4)) +@@ -74,13 +92,13 @@ receiving multiple values. + ((x y) (values a b))) + (list a b x y))) --> (x y a b) + </pre> +-</p> +- +-<dt><a name="let*-values"></a> ++</dd> ++<dt id="let*-values"> + <tt>(LET*-VALUES ((<formals> <expression>) ...) <body>)</tt> +-<br>Syntax ++<br />Syntax ++</dt> + <dd> +-<p>Each <formals> should be a formal arguments list as for a LAMBDA ++<p>Each <formals> should be a formal arguments list as for a LAMBDA + expression, cf section 4.1.4 of the R5RS.</p> + + <p>LET*-VALUES is similar to LET-VALUES, but the bindings are performed +@@ -89,26 +107,25 @@ receiving multiple values. + expression to the right of the binding. Thus the second binding is done in + an environment in which the first binding is visible, and so on.</p> + +-<p> + <pre> + (let ((a 'a) (b 'b) (x 'x) (y 'y)) + (let*-values (((a b) (values x y)) + ((x y) (values a b))) + (list a b x y))) --> (x y x y) + </pre> +-</p> ++</dd> + </dl> + +-<H1>Implementation</H1> + ++<h2>Implementation</h2> ++<p> + The following implementation is written in R5RS Scheme. It is not + compatible with the IEEE Scheme standard because the IEEE standard does + not contain the high-level macro system. +- ++</p> + <p>The implementation assumes that some top-level names defined by the + R5RS are bound to their original values. +- +-<p> ++</p> + <pre> + ;; This code is in the public domain. + +@@ -148,9 +165,8 @@ R5RS are bound to their original values. + (let*-values (?binding1 ...) ?body0 ?body1 ...))))) + </pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Lars T Hansen (1999). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -173,12 +189,11 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> +- +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Tue Sep 28 10:59:57 MST 2004 ++Last modified: Sun Jan 28 13:40:20 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html +index 2f744dc..b519905 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-13.html +@@ -1,22 +1,39 @@ +-<!doctype html public '-//W3C//DTD HTML 4.01//EN' +- 'http://www.w3.org/TR/REC-html4/strict.dtd'> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/REC-html4/strict.dtd"> ++<html lang="en-US"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-13 ┃ ++┃ Commit: 84ebb079e9b446b5a067d6fcdba95932a1fe7cf0 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <!-- Can I have bangs, plusses, or slashes in #tags? Spaces? + Yes: plus, bang, star No: space Yes: slash, question, ampersand + You can't put sharp in a path, so anything goes, really. + Nonetheless, some of these confuse Netscape, so I'll avoid them. + --> +- + <!--========================================================================--> +-<html lang=en-US> +- <head> +- <meta name="keywords" content="Scheme, programming language, list processing, SRFI, youthful devotees of intra-gender communion"> +- <link rev=made href="mailto:shivers@ai.mit.edu"> ++ <meta content="Scheme, programming language, list processing, SRFI" name="keywords" /> + <title>SRFI 13: String Libraries</title> +- ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + <!-- Should have a media=all to get, for example, printing to work. + == But my Netscape will completely ignore the tag if I do that. + --> + <style type="text/css"> ++ /*<![CDATA[*/ + /* A little general layout hackery for headers & the title. */ + body { margin-left: +7%; + font-family: "Helvetica", sans-serif; +@@ -28,11 +45,11 @@ + + div.inset { margin-left: +5%; } + +- h1 { margin-left: -5%; } +- h1, h2 { clear: both; } ++ h2 { margin-left: -5%; } ++ h2, h3 { clear: both; } + h1, h2, h3, h4, h5, h6 { color: blue } + div.title-text { font-size: large; font-weight: bold; } +- h3 { margin-top: 2em; margin-bottom: 0em } ++ h4 { margin-top: 2em; margin-bottom: 0em } + + /* "Continue" class marks text that isn't really the start + ** of a new paragraph -- e.g., continuing a para after a +@@ -106,9 +123,11 @@ + ** development process and kill them when the document's done. + */ + a.draft { color: red; } ++ /*]]>*/ + </style> + +- <style type="text/css" media=all> ++ <style media="all" type="text/css"> ++ /*<![CDATA[*/ + /* Nastiness: Here, I'm using a bug to work around a bug. + ** Netscape rendering bugs mean you need bogus <dt> and <dd> + ** margin settings -- settings which screw up IE's proper rendering. +@@ -135,152 +154,155 @@ + /* Spread out bibliographic lists. */ + dt.biblio { margin-top: 3ex; margin-bottom: 0ex; } + dd.biblio { margin-bottom: 1ex; } ++ /*]]>*/ + </style> + </head> + + <body> + + <!--========================================================================--> +-<H1>Title</H1> ++<h1>SRFI 13: String Libraries</h1> + +-<div class=title-text>SRFI 13: String Libraries</div> ++<p>by Olin Shivers</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 13 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-13/srfi-13.html">https://srfi.schemers.org/srfi-13/srfi-13.html</a>.</p></blockquote></blockquote></blockquote> + +-<!--========================================================================--> +-<H1>Author</H1> +- +-Olin Shivers +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-13/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/10/17 +-<LI>Draft: 1999/10/18-1999/12/16 +-<LI>Revised: 1999/10/31 +-<LI>Revised: 1999/11/13 +-<LI>Revised: 1999/11/22 +-<LI>Revised: 2000/04/30 +-<LI>Revised: 2000/06/09 +-<LI>Revised: 2000/12/23 +-</UL> +- +-<h1>Table of contents</H1> ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+13+at+srfi+dotschemers+dot+org">srfi-13@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-13">archive</a>.</p> ++<ul> ++<li>Received: 1999-10-17 ++</li><li>Draft: 1999-10-18--1999-12-16 ++</li><li>Revised: 1999-10-31 ++</li><li>Revised: 1999-11-13 ++</li><li>Revised: 1999-11-22 ++</li><li>Revised: 2000-04-30 ++</li><li>Revised: 2000-06-09 ++</li><li>Revised: 2000-12-23 ++</li></ul> ++ ++<h2>Table of contents</h2> + + <!-- A bug in netscape (?) keeps the first link in this UL from being active. + ==== So the Abstract link be dead. 99/8/22 -Olin + --> +-<ul id=toc-table> ++<ul id="toc-table"> + <li><a href="#Abstract">Abstract</a> +-<li><a href="#ProcedureIndex">Procedure index</a> +-<li><a href="#Rationale">Rationale</a> ++</li><li><a href="#ProcedureIndex">Procedure index</a> ++</li><li><a href="#Rationale">Rationale</a> + <ul> + <li><a href="#StringsAreCodePointSeqs">Strings are code-point sequences</a> +- <li><a href="#NoLocales">String operations are locale- and context-independent</a> +- <li><a href="#Unicode">Internationalisation & super-ASCII character types</a> ++ </li><li><a href="#NoLocales">String operations are locale- and context-independent</a> ++ </li><li><a href="#Unicode">Internationalisation & super-ASCII character types</a> + <ul> + <li><a href="#Case">Case mapping and case folding</a> +- <li><a href="#Eq">String equality & string normalisation</a> +- <li><a href="#Ineq">String inequality</a> +- </ul> +- <li><a href="#NamingConventions">Naming conventions</a> +- <li><a href="#SharedStorage">Shared storage</a> +- <li><a href="#R5RS-procs">R4RS/R5RS procedures</a> +- <li><a href="#ExtraSRFI">Extra-SRFI recommendations</a> +- </ul> +- +-<li><a href="#Procedures">Procedure specification</a> ++ </li><li><a href="#Eq">String equality & string normalisation</a> ++ </li><li><a href="#Ineq">String inequality</a> ++ </li></ul> ++ </li><li><a href="#NamingConventions">Naming conventions</a> ++ </li><li><a href="#SharedStorage">Shared storage</a> ++ </li><li><a href="#R5RS-procs">R4RS/R5RS procedures</a> ++ </li><li><a href="#ExtraSRFI">Extra-SRFI recommendations</a> ++ </li></ul> ++ ++</li><li><a href="#Procedures">Procedure specification</a> + <ul> + <li><a href="#MainProcs">Main procedures</a> + <ul> + <li><a href="#Predicates">Predicates</a> +- <li><a href="#Constructors">Constructors</a> +- <li><a href="#List2String">List & string conversion</a> +- <li><a href="#Selection">Selection</a> +- <li><a href="#Modification">Modification</a> +- <li><a href="#Comparison">Comparison</a> +- <li><a href="#PrefixesSuffixes">Prefixes & suffixes</a> +- <li><a href="#Searching">Searching</a> +- <li><a href="#CaseMapping">Alphabetic case mapping</a> +- <li><a href="#ReverseAppend">Reverse & append</a> +- <li><a href="#FoldUnfoldMap">Fold, unfold & map</a> +- <li><a href="#ReplicateRotate">Replicate & rotate</a> +- <li><a href="#Miscellaneous">Miscellaneous: insertion, parsing</a> +- <li><a href="#FilterDelete">Filtering & deleting</a> +- </ul> +- +- <li><a href="#LowLevelProcs">Low-level procedures</a> ++ </li><li><a href="#Constructors">Constructors</a> ++ </li><li><a href="#List2String">List & string conversion</a> ++ </li><li><a href="#Selection">Selection</a> ++ </li><li><a href="#Modification">Modification</a> ++ </li><li><a href="#Comparison">Comparison</a> ++ </li><li><a href="#PrefixesSuffixes">Prefixes & suffixes</a> ++ </li><li><a href="#Searching">Searching</a> ++ </li><li><a href="#CaseMapping">Alphabetic case mapping</a> ++ </li><li><a href="#ReverseAppend">Reverse & append</a> ++ </li><li><a href="#FoldUnfoldMap">Fold, unfold & map</a> ++ </li><li><a href="#ReplicateRotate">Replicate & rotate</a> ++ </li><li><a href="#Miscellaneous">Miscellaneous: insertion, parsing</a> ++ </li><li><a href="#FilterDelete">Filtering & deleting</a> ++ </li></ul> ++ ++ </li><li><a href="#LowLevelProcs">Low-level procedures</a> + <ul> + <li><a href="#ArgUtils">Start/end optional argument parsing & checking utilities</a> +- <li><a href="#KMP">Knuth-Morris-Pratt searching</a> +- </ul> +- </ul> ++ </li><li><a href="#KMP">Knuth-Morris-Pratt searching</a> ++ </li></ul> ++ </li></ul> + +-<li><a href="#ReferenceImp">Reference implementation</a> +-<li><a href="#Acknowledgements">Acknowledgements</a> +-<li><a href="#Links">References & Links</a> +-<li><a href="#Copyright">Copyright</a> +-</ul> ++</li><li><a href="#ReferenceImp">Reference implementation</a> ++</li><li><a href="#Acknowledgements">Acknowledgements</a> ++</li><li><a href="#Links">References & Links</a> ++</li><li><a href="#Copyright">Copyright</a> ++</li></ul> + + <!--========================================================================--> +-<h1><a name="Abstract">Abstract</a></H1> ++<h2 id="Abstract">Abstract</h2> + <p> + + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + Scheme has an impoverished set of string-processing utilities, which is a +-problem for authors of portable code. This <abbr title="Scheme Request for +-Implementation">SRFI</abbr> proposes a coherent and comprehensive set of ++problem for authors of portable code. ++This <abbr title="Scheme Request for Implementation">SRFI</abbr> proposes ++a coherent and comprehensive set of + string-processing procedures; it is accompanied by a reference implementation + of the spec. The reference implementation is ++</p> + <ul> + <li>portable +-<li>efficient +-<li>open source +-</ul> ++</li><li>efficient ++</li><li>open source ++</li></ul> + <p> + The routines in this SRFI are backwards-compatible with the string-processing + routines of + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>. +- ++</p> + <!--========================================================================--> +-<h1><a name="ProcedureIndex">Procedure Index</a></h1> ++<h2 id="ProcedureIndex">Procedure Index</h2> + <p> + Here is a list of the procedures provided by the string-lib + and string-lib-internals packages. + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + procedures are shown in +-<span class=r5rs-proc>bold</span>; ++<span class="r5rs-proc">bold</span>; + extended <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + +- procedures, in <span class=r5rs-procx>bold italic</span>. +-<div class=indent> ++ procedures, in <span class="r5rs-procx">bold italic</span>. ++</p> ++<div class="indent"> + <dl> +-<dt class=proc-index> Predicates +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#string-p">string?</a></span> <a href="#string-null-p">string-null?</a> ++<dt class="proc-index"> Predicates ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#string-p">string?</a></span> <a href="#string-null-p">string-null?</a> + <a href="#string-every">string-every</a> <a href="#string-any">string-any</a> + </pre> + +-<dt class=proc-index> Constructors +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#make-string">make-string</a> <a href="#string">string</a></span> <a href="#string-tabulate">string-tabulate</a> ++</dd><dt class="proc-index"> Constructors ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#make-string">make-string</a> <a href="#string">string</a></span> <a href="#string-tabulate">string-tabulate</a> + </pre> + +-<dt class=proc-index> List & string conversion +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-procx><a href="#string2list">string->list</a></span> <span class=r5rs-proc><a href="#list2string">list->string</a></span> +-<a href="#reverse-list2string">reverse-list->string</a> <a href="#string-join">string-join</a> ++</dd><dt class="proc-index"> List & string conversion ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-procx"><a href="#string2list">string->list</a></span> <span class="r5rs-proc"><a href="#list2string">list->string</a></span> ++<a href="#reverse-list2string">reverse-list->string</a> <a href="#string-join">string-join</a> + </pre> + +-<dt class=proc-index> Selection +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#string-length">string-length</a> ++</dd><dt class="proc-index"> Selection ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#string-length">string-length</a> + <a href="#string-ref">string-ref</a></span> +-<span class=r5rs-procx><a href="#string-copy">string-copy</a></span> +-<a href="#substring/shared">substring/shared</a> ++<span class="r5rs-procx"><a href="#string-copy">string-copy</a></span> ++<a href="#substring%2Fshared">substring/shared</a> + <a href="#string-copy!">string-copy!</a> + <a href="#string-take">string-take</a> <a href="#string-take-right">string-take-right</a> + <a href="#string-drop">string-drop</a> <a href="#string-drop-right">string-drop-right</a> +@@ -288,24 +310,24 @@ extended <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr + <a href="#string-trim">string-trim</a> <a href="#string-trim-right">string-trim-right</a> <a href="#string-trim-both">string-trim-both</a> + </pre> + +-<dt class=proc-index>Modification +-<dd class=proc-index> +-<pre class=proc-index> +-<span class=r5rs-proc><a href="#string-set!">string-set!</a></span> <span class=r5rs-procx><a href="#string-fill!">string-fill!</a></span> ++</dd><dt class="proc-index">Modification ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<span class="r5rs-proc"><a href="#string-set!">string-set!</a></span> <span class="r5rs-procx"><a href="#string-fill!">string-fill!</a></span> + </pre> + +-<dt class=proc-index>Comparison +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Comparison ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-compare">string-compare</a> <a href="#string-compare-ci">string-compare-ci</a> +-<a href="#string<>">string<></a> <a href="#string=">string=</a> <a href="#string<">string<</a> <a href="#string>">string></a> <a href="#string<=">string<=</a> <a href="#string>=">string>=</a> +-<a href="#string-ci<>">string-ci<></a> <a href="#string-ci=">string-ci=</a> <a href="#string-ci<">string-ci<</a> <a href="#string-ci>">string-ci></a> <a href="#string-ci<=">string-ci<=</a> <a href="#string-ci>=">string-ci>=</a> ++<a href="#string%3C%3E">string<></a> <a href="#string%3D">string=</a> <a href="#string%3C">string<</a> <a href="#string%3E">string></a> <a href="#string%3C%3D">string<=</a> <a href="#string%3E%3D">string>=</a> ++<a href="#string-ci%3C%3E">string-ci<></a> <a href="#string-ci%3D">string-ci=</a> <a href="#string-ci%3C">string-ci<</a> <a href="#string-ci%3E">string-ci></a> <a href="#string-ci%3C%3D">string-ci<=</a> <a href="#string-ci%3E%3D">string-ci>=</a> + <a href="#string-hash">string-hash</a> <a href="#string-hash-ci">string-hash-ci</a> + </pre> + +-<dt class=proc-index>Prefixes & suffixes +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Prefixes & suffixes ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-prefix-length">string-prefix-length</a> <a href="#string-suffix-length">string-suffix-length</a> + <a href="#string-prefix-length-ci">string-prefix-length-ci</a> <a href="#string-suffix-length-ci">string-suffix-length-ci</a> + +@@ -313,65 +335,65 @@ extended <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr + <a href="#string-prefix-ci-p">string-prefix-ci?</a> <a href="#string-suffix-ci-p">string-suffix-ci?</a> + </pre> + +-<dt class=proc-index>Searching +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Searching ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-index">string-index</a> <a href="#string-index-right">string-index-right</a> + <a href="#string-skip">string-skip</a> <a href="#string-skip-right">string-skip-right</a> + <a href="#string-count">string-count</a> + <a href="#string-contains">string-contains</a> <a href="#string-contains-ci">string-contains-ci</a> + </pre> + +-<dt class=proc-index>Alphabetic case mapping +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Alphabetic case mapping ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-titlecase">string-titlecase</a> <a href="#string-upcase">string-upcase</a> <a href="#string-downcase">string-downcase</a> + <a href="#string-titlecase!">string-titlecase!</a> <a href="#string-upcase!">string-upcase!</a> <a href="#string-downcase!">string-downcase!</a> + </pre> + +-<dt class=proc-index>Reverse & append +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Reverse & append ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-reverse">string-reverse</a> <a href="#string-reverse!">string-reverse!</a> +-<span class=r5rs-proc><a href="#string-append">string-append</a></span> ++<span class="r5rs-proc"><a href="#string-append">string-append</a></span> + <a href="#string-concatenate">string-concatenate</a> +-<a href="#string-concatenate/shared">string-concatenate/shared</a> <a href="#string-append/shared">string-append/shared</a> +-<a href="#string-concatenate-reverse">string-concatenate-reverse</a> <a href="#string-concatenate-reverse/shared">string-concatenate-reverse/shared</a> ++<a href="#string-concatenate%2Fshared">string-concatenate/shared</a> <a href="#string-append%2Fshared">string-append/shared</a> ++<a href="#string-concatenate-reverse">string-concatenate-reverse</a> <a href="#string-concatenate-reverse%2Fshared">string-concatenate-reverse/shared</a> + </pre> + +-<dt class=proc-index>Fold, unfold & map +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Fold, unfold & map ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-map">string-map</a> <a href="#string-map!">string-map!</a> + <a href="#string-fold">string-fold</a> <a href="#string-fold-right">string-fold-right</a> + <a href="#string-unfold">string-unfold</a> <a href="#string-unfold-right">string-unfold-right</a> + <a href="#string-for-each">string-for-each</a> <a href="#string-for-each-index">string-for-each-index</a> + </pre> + +-<dt class=proc-index>Replicate & rotate +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Replicate & rotate ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#xsubstring">xsubstring</a> <a href="#string-xcopy!">string-xcopy!</a> + </pre> + +-<dt class=proc-index>Miscellaneous: insertion, parsing +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Miscellaneous: insertion, parsing ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-replace">string-replace</a> <a href="#string-tokenize">string-tokenize</a> + </pre> + +-<dt class=proc-index>Filtering & deleting +-<dd class=proc-index> +-<pre class=proc-index> ++</dd><dt class="proc-index">Filtering & deleting ++</dt><dd class="proc-index"> ++<pre class="proc-index"> + <a href="#string-filter">string-filter</a> <a href="#string-delete">string-delete</a> + </pre> + +-<dt class=proc-index>Low-level procedures +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#string-parse-start+end">string-parse-start+end</a> +-<a href="#string-parse-final-start+end">string-parse-final-start+end</a> +-<a href="#let-string-start+end">let-string-start+end</a> ++</dd><dt class="proc-index">Low-level procedures ++</dt><dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#string-parse-start%2Bend">string-parse-start+end</a> ++<a href="#string-parse-final-start%2Bend">string-parse-final-start+end</a> ++<a href="#let-string-start%2Bend">let-string-start+end</a> + + <a href="#check-substring-spec">check-substring-spec</a> + <a href="#substring-spec-ok-p">substring-spec-ok?</a> +@@ -379,35 +401,34 @@ extended <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr + <a href="#make-kmp-restart-vector">make-kmp-restart-vector</a> <a href="#kmp-step">kmp-step</a> <a href="#string-kmp-partial-search">string-kmp-partial-search</a> + </pre> + +-</dl> ++</dd></dl> + </div> + + <!--========================================================================--> +-<h1><a name="Rationale">Rationale</a></h1> ++<h2 id="Rationale">Rationale</h2> + <p> +- + This SRFI defines two libraries that provide a rich set of operations for + manipulating strings. These are frequently useful for scripting and other + text-manipulation applications. The library's design was influenced by the + string libraries found in MIT Scheme, Gambit, RScheme, MzScheme, slib, Common + Lisp, Bigloo, guile, Chez, APL, Java, and the SML standard basis. ++</p> + <p> +- + All procedures involving character comparison are available in + both case-sensitive and case-insensitive forms. ++</p> + <p> +- + All functionality is available in substring and full-string forms. +- ++</p> + <!--========================================================================--> +-<h2><a name="StringsAreCodePointSeqs">Strings are code-point sequences</a></h2> ++<h3 id="StringsAreCodePointSeqs">Strings are code-point sequences</h3> + <p> + This SRFI considers strings simply to be a sequence of "code points" or + character encodings. Operations such as comparison or reversal are always done + code point by code point. See the comments below on super-ASCII character + types for implications that follow. ++</p> + <p> +- + It's entirely possible that a legal string might not be a sensible "text" + sequence. For example, consider a string comprised entirely of zero-width + Unicode accent characters with no preceding base character to modify -- +@@ -415,11 +436,10 @@ this is a legal string, albeit one that does not make a great deal of sense + when interpreted as a sequence of natural-language text. The routines in + this SRFI do not handle these "text" concerns; they restrict themselves + to the underlying view of strings as merely a sequence of "code points." +- ++</p> + <!--========================================================================--> +-<h2><a name="NoLocales">String operations are locale- and context-independent</a></h2> ++<h3 id="NoLocales">String operations are locale- and context-independent</h3> + <p> +- + This SRFI defines string operations that are locale- and context-independent. + While it is certainly important to have a locale-sensitive comparison or + collation procedure when processing text, it is also important to have a suite +@@ -427,14 +447,13 @@ of operations that are reliably invariant for basic string processing --- + otherwise, a change of locale could cause data structures such as hash tables, + b-trees, symbol tables, directories of filenames, <em>etc.</em> + to become corrupted. +- ++</p> + <p> + Locale- and context-sensitive text operations, such as collation, are + explicitly deferred to a subsequent, companion "text" SRFI. +- ++</p> + <!--========================================================================--> +-<h2><a name="Unicode">Internationalisation & super-ASCII character types</a></h2> +- ++<h3 id="Unicode">Internationalisation & super-ASCII character types</h3> + <p> + The major issue confronting this SRFI is the existence of super-ASCII + character encodings, such as eight-bit Latin-1 or 16- and 32-bit Unicode. It +@@ -443,13 +462,13 @@ implementations based on at least these three standard encodings. + Unfortunately, this places strong limitations on the API design. Here are + some relevant issues. Be warned that life in a super-ASCII world is + significantly more complex; there are no easy answers for many of these issues. +- ++</p> + <!--========================================================================--> +-<h3><a name="Case">Case mapping and case-folding</a></h3> ++<h4 id="Case">Case mapping and case-folding</h4> + + <p> + Upper- and lower-casing characters is complex in super-ASCII encodings. +- ++</p> + <ul> + <li> Some characters case-map to more than one character. For example, + the Latin-1 German eszet character upper-cases to "SS." +@@ -458,20 +477,22 @@ Upper- and lower-casing characters is complex in super-ASCII encodings. + <a href="#R5RS">R5RS</a></abbr> function <code>char-upcase</code> is not well-defined, + since it is defined to produce a (single) character result. + +- <li> It means that an in-place <code>string-upcase!</code> procedure cannot be reliably ++ </li><li> It means that an in-place <code>string-upcase!</code> procedure cannot be reliably + defined, since the original string may not be long enough to contain + the result -- an N-character string might upcase to a 2N-character result. + +- <li> It means that case-insensitive string-matching or searching is quite ++ </li><li> It means that case-insensitive string-matching or searching is quite + tricky. For example, an n-character string <var>s</var> might match a 2N-character + string <var>s'</var>. +- </ul> ++ </li></ul> + ++</li> + <li> Some characters case-map in different ways depending upon their surrounding + context. For example, the Unicode Greek capital sigma character downcases + differently depending upon whether or not it is the final character in a + word. Again, this spells trouble for the simple <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> <code>char-downcase</code> function. + ++</li> + <li> Unicode defines three cases: lowercase, uppercase and titlecase. The + distinction between uppercase and titlecase arises in the presence of + Unicode's compound characters. For example, Unicode has a single character +@@ -479,18 +500,22 @@ Upper- and lower-casing characters is complex in super-ASCII encodings. + the compound character "DZ", while titlecasing (or, as Americans say, + capitalizing) it produces compound character "Dz". + ++</li> + <li> Turkish actually has different case-mappings from other languages. ++</li> + </ul> + + <p> +-The Unicode Consortium's web site +-<div class=inset> ++ The Unicode Consortium's web site ++</p> ++<div class="inset"> + <a href="http://www.unicode.org/">http://www.unicode.org/</a> + </div> +-<p class=continue> ++<p class="continue"> + has detailed discussions of the issues. See in particular technical report + 21 on case mappings +-<div class=inset> ++</p> ++<div class="inset"> + <a href="http://www.unicode.org/unicode/reports/tr21/">http://www.unicode.org/unicode/reports/tr21/</a> + </div> + +@@ -498,24 +523,26 @@ has detailed discussions of the issues. See in particular technical report + SRFI 13 makes no attempt to deal with these issues; it uses a simple 1-1 + locale- and context-independent case-mapping, specifically Unicode's 1-1 + case-mappings given in +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +-<p class=continue> ++<p class="continue"> + The format of this file is explained in +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html</a> + </div> +-<p class=continue> ++<p class="continue"> + Note that this means that German eszet upper-cases to itself, not "SS". + +-<p> ++</p><p> + Case-mapping and case-folding operations in SRFI 13 are locale-independent so + that shifting locales won't wreck hash tables, b-trees, symbol tables, <em>etc.</em> +- ++</p> + + <!--========================================================================--> +-<h3><a name="Eq">String equality & string normalisation</a></h3> ++<h4><a name="Eq">String equality & string normalisation</a></h4> + + <p> + Comparing strings for equality is complicated because in some cases Unicode +@@ -526,31 +553,32 @@ an acute accent. There is a single Unicode character for this. However, + Unicode also allows one to represent this with a two-character sequence: the + "e" character followed by a zero-width acute-accent character. As another + example, Unicode provides some Asian characters in "narrow" and "full" widths. +- ++</p> + <p> + There are multiple ways we might want to compare strings for equality. In + (roughly) decreasing order of precision, +- ++</p> + <ul> + <li> we might want a precise comparison of the actual encoding, so that + <e-acute> would <em>not</em> compare equal to <e, acute>. +- +-<li> We might want a "normalised" comparison, where these two sequences ++</li> ++<li> We might want a "normalised" comparison, where these two sequences + would compare equal. +- ++</li> + <li> We might want an even more-permissive normalisation, where visually-distinct + properties of "the same" character would be ignored. For example, we might + want narrow/full-width versions of the same Asian character to compare equal. +- ++</li> + <li> We might want comparisons that are insensitive to accents and diacritical + marks. +- ++</li> + <li> We might want comparisons that are case-insensitive. +- ++</li> + <li> We might want comparisons that are insensitive to several of the above + properties. +- ++</li> + <li> We might want ways to "normalise" strings into various canonical forms. ++</li> + </ul> + + <p> +@@ -559,24 +587,26 @@ simply based upon comparing the encoding values used for the characters. + Accent-insensitive and other types of comparison are not provided; only + a simple form of case-insensitive comparison is provided, which uses the + 1-1 case mappings specified by Unicode in +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +-<p class=continue> ++<p class="continue"> + These are adequate for "program" or "systems" use of strings (<em>e.g.</em>, to + manipulate program identifiers and operating-system filenames). +- ++</p> + <!--========================================================================--> +-<h3><a name="Ineq">String inequality</a></h3> ++<h4><a name="Ineq">String inequality</a></h4> + + <p> + Above and beyond the issues arising in string-equality, when we attempt + to order strings there are even further considerations. +- ++</p> + <ul> + <li> French orders accents with right-to-left significance -- the reverse of + the significance of the characters. + ++</li> + <li> Case-insensitive ordering is not well defined by simple "code-point" + considerations, even for simple ASCII: there are punctuation characters + between the ASCII's upper-case range of letters and its lower-case range +@@ -584,8 +614,10 @@ to order strings there are even further considerations. + Does left-bracket compare less-than or greater-than "a" in a + case-insensitive comparison? + ++</li> + <li> The German eszet character should sort as if it were the <em>pair</em> of + letters "ss". ++</li> + </ul> + + <p> +@@ -596,9 +628,9 @@ can be overlaid by additional domain- or language-specific rules. Again, + this SRFI does not address these issues. SRFI 13 string ordering is strictly + based upon a character-by-character comparison of the values used for + representing the string. +- ++</p> + <!--========================================================================--> +-<h2><a name="NamingConventions">Naming conventions</a></h2> ++<h3 id="NamingConventions">Naming conventions</h3> + + <p> + This library contains a large number of procedures, but they follow +@@ -608,22 +640,25 @@ in a regular way that exposes the structure and relationships between the + procedures. This should help the programmer to recall or reconstitute the name + of the particular procedure that he needs when writing his own code. In + particular +- ++</p> + <ul> + <li> Procedures whose names end in "-ci" are case-insensitive variants. + ++ </li> + <li> Procedures whose names end in "!" are side-effecting variants. + What values these procedures return is usually not specified. + ++ </li> + <li> The order of common parameters is consistent across the + different procedures. + ++ </li> + <li> Left/right/both directionality: + Procedures that have left/right directional variants + use the following convention: +- <div class=indent> +- <table cellspacing=0 cellpadding=0> +- <tr align=left><th>Direction</th> ++ <div class="indent"> ++ <table cellpadding="0" cellspacing="0"> ++ <tr align="left"><th>Direction</th> + <th> </th> + <th>Suffix</th></tr> + <tr><td>left-to-right</td><td></td><td><em>none</em></td></tr> +@@ -635,10 +670,11 @@ particular + This is a general convention that was established in SRFI 1. + The value of a convention is proportional to the extent of its + use. ++ </li> + </ul> + + <!--========================================================================--> +-<h2><a name="SharedStorage">Shared storage</a></h2> ++<h3 id="SharedStorage">Shared storage</h3> + + <p> + Some Scheme implementations, <em>e.g.</em> guile and T, provide ways to construct +@@ -651,12 +687,12 @@ property of these substrings -- the application assumes that if the underlying + storage is mutated, then all strings sharing that storage will show the + change. However, shared-text substrings are not a common feature; most Scheme + implementations do not provide them. +- ++</p> + <p> + SRFI 13 takes a middle ground with respect to shared-text substrings. In + particular, a Scheme implementation does not need to have shared-text + substrings in order to implement this SRFI. +- ++</p> + <p> + There is an additional form of storage sharing enabled by some SRFI 13 + procedures, even without the benefit of shared-text substrings. In +@@ -665,40 +701,44 @@ of the strings that was passed in as a parameter. For example, when + constructing a substring with the <code>substring/shared</code> procedure, if the + requested substring is the entire string, the procedure is permitted + simply to return the original value. That is, +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (eq? s (substring/shared s 0 (string-length s))) => true or false + </pre> +-<p class=continue> ++<p class="continue"> + whereas the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + <code>substring</code> function is required to allocate a fresh copy +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (eq? s (substring s 0 (string-length s))) => false. + </pre> + <p> + In keeping with SRFI 13's general approach to sharing, compliant + implementations are allowed, but not required, to provide this kind of + sharing. Hence, procedures may not <em>rely</em> upon sharing in these cases. +-<p class=continue> ++</p> ++<p class="continue"> + Most procedures that permit results to share storage with inputs have + equivalent procedures that require allocating fresh storage for results. + If an application wishes to be sure a new, fresh string is allocated, then + these "pure" procedures should be used. +-<div class=inset> +-<table cellpadding=0 cellspacing=0> +-<tr align=left><th>Fresh copy guaranteed</th> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> ++<tr align="left"><th>Fresh copy guaranteed</th> + <th>Sharing permitted</th></tr> + <tr><td><code>string-copy</code></td> + <td><code>substring/shared</code></td></tr> + <tr><td><code>string-copy</code></td> + <td><code>string-take string-take-right</code></td></tr> + <tr><td><code>string-copy</code></td> +- <td><code>string-drop string-drop-right</code></tr> ++ <td><code>string-drop string-drop-right</code></td></tr> + <tr><td><code>string-concatenate</code></td> +- <td><code>string-concatenate/shared</code></tr> ++ <td><code>string-concatenate/shared</code></td></tr> + <tr><td><code>string-append</code></td> + <td><code>string-append/shared</code></td></tr> + <tr><td><code>string-concatenate-reverse</code> +- <td><code>string-concatenate-reverse/shared</code></td></tr> ++ </td><td><code>string-concatenate-reverse/shared</code></td></tr> + <tr><td></td> + <td><code>string-pad string-pad-right</code></td></tr> + <tr><td></td> +@@ -719,16 +759,16 @@ without this consideration -- if we had cheap shared-text substrings, all the + start/end index parameters would vanish. However, since SRFI 13 does not + require implementations to provide shared-text substrings, the extended + API is provided. +- ++</p> + <!--========================================================================--> +-<h2><a name="R5RS-procs">R4RS/R5RS procedures</a></h2> ++<h3 id="R5RS-procs">R4RS/R5RS procedures</h3> + + <p> + The R4RS and <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> reports define 22 string procedures. The string-lib + package includes 8 of these exactly as defined, 3 in an extended, + backwards-compatible way, and drops the remaining 11 (whose functionality + is available via other bindings). +- ++</p> + <p> + The 8 procedures provided exactly as documented in the reports are + <code>string?</code>, +@@ -739,7 +779,7 @@ The 8 procedures provided exactly as documented in the reports are + <code>string-set!</code>, + <code>string-append</code>, and + <code>list->string</code>. +- ++</p> + <p> + The eleven functions not included are + <code>string=?</code>, <code>string-ci=?</code>, +@@ -749,37 +789,44 @@ The eleven functions not included are + <code>string>=?</code>, <code>string-ci>=?</code>, and + <code>substring</code>. + The string-lib package provides alternate bindings and extended functionality. +- ++</p> + <p> + Additionally, the three extended procedures are +-<pre class=code-example> ++</p> ++<pre class="code-example"> + string-fill! <var>s char [start end] -> unspecified</var> + string->list <var>s [start end] -> char-list</var> + string-copy <var>s [start end] -> string</var> + </pre> +-<p class=continue> ++<p class="continue"> + They are uniformly extended to take optional start/end parameters specifying + substring ranges. +- ++</p> + <!--========================================================================--> +-<h2><a name="ExtraSRFI">Extra-SRFI recommendations</a></h2> ++<h3 id="ExtraSRFI">Extra-SRFI recommendations</h3> + + <p> + This SRFI recommends the following +- ++</p> + <ul> +-<li> A SRFI be defined for shared-text substrings, allowing programs to ++ <li> ++ <p> ++ A SRFI be defined for shared-text substrings, allowing programs to + be written that actually rely on the shared-storage properties of these data + structures. +- +-<li> A SRFI be defined for manipulating Unicode text -- various normalisation ++ </p> ++ </li> ++ <li> ++ <p> ++ A SRFI be defined for manipulating Unicode text -- various normalisation + operations, collation, searching, <em>etc.</em> Collation operations might be + parameterised by a "collation" structure representing collation rules + for a particular locale or language. Alternatively, a data structure + specifying collation rules could be activated with dynamic scope by + special procedures, possibly overridden by allowing collation rules + to be optional arguments to procedures that need to order strings, <em>e.g.</em> +-<pre class=code-example> ++ </p> ++<pre class="code-example"> + (with-locale* denmark-locale + (lambda () + (f x) +@@ -792,28 +839,32 @@ This SRFI recommends the following + + (set-locale! denmark-locale) + </pre> +- +-<li> A SRFI be defined for manipulating characters that is portable across ++ </li> ++ <li> ++ <p> ++ A SRFI be defined for manipulating characters that is portable across + at least ASCII, Latin-1 and Unicode. +- +- <ul> ++ </p> ++ <ul> + <li> For backwards-compatibility, <code>char-upcase</code> and <code>char-downcase</code> should + be defined to use the 1-1 locale- and context-insensitive case + mappings given by Unicode's UnicodeData.txt table. +- ++ </li> + <li> numeric codes for standard functions that map between characters and + integers should be required to use the Unicode/Latin-1/ASCII mapping. This + allows programmers to write portable code. +- ++ </li> + <li> <code>char-titlecase</code> be added to <code>char-upcase</code> and <code>char-downcase</code>. +- ++ </li> + <li> <code>char-titlecase?</code> be added to <code>char-upcase?</code> and <code>char-downcase?</code>. +- ++ </li> + <li> Title/up/down-case functions be added to the character-processing suite + which allow 1->n case maps by returning immutable, + possibly-multi-character strings instead of single characters. These case + mappings need not be locale- or context-sensitive. +- </ul> ++ </li> ++ </ul> ++ </li> + </ul> + + <p> +@@ -821,75 +872,83 @@ This SRFI recommends the following + requiring a Unicode/Latin-1/ASCII interface to integer/char mapping + functions does not imply anything about the actual underlying encodings of + characters. +- ++</p> + + <!--========================================================================--> +-<h1><a name="Procedures">Procedure Specification</a></h1> ++<h2 id="Procedures">Procedure Specification</h2> + + <p> + In the following procedure specifications: ++</p> + <ul> + <li> An <var>s</var> parameter is a string. +- ++ </li> + <li> A <var>char</var> parameter is a character. +- +- <li> <var>Start</var> and <var>end</var> parameters are half-open string indices specifying ++ </li> ++ <li> <var>Start</var> and <var>end</var> parameters are half-open string indices specifying + a substring within a string parameter; when optional, they default + to 0 and the length of the string, respectively. When specified, it + must be the case that 0 <= <var>start</var> <= <var>end</var> + <= <code>(string-length <var>s</var>)</code>, for + the corresponding parameter <var>s</var>. They typically restrict a procedure's + action to the indicated substring. +- +- <li> A <var>pred</var> parameter is a unary character predicate procedure, returning ++ </li> ++ <li> A <var>pred</var> parameter is a unary character predicate procedure, returning + a true/false value when applied to a character. +- ++ </li> + <li> A <var>char/char-set/pred</var> parameter is a value used to select/search + for a character in a string. If it is a character, it is used in + an equality test; if it is a character set, it is used as a + membership test; if it is a procedure, it is applied to the + characters as a test predicate. +- ++ </li> + <li> An <var>i</var> parameter is an exact non-negative integer specifying an index + into a string. +- ++ </li> + <li> <var>Len</var> and <var>nchars</var> parameters are exact non-negative integers specifying a + length of a string or some number of characters. +- ++ </li> + <li> An <var>obj</var> parameter may be any value at all. ++ </li> + </ul> +-<p class=continue> ++<p class="continue"> + Passing values to procedures with these parameters that do not satisfy these + types is an error. +- ++</p> + <p> + Parameters given in square brackets are optional. Unless otherwise noted in the + text describing the procedure, any prefix of these optional parameters may + be supplied, from zero arguments to the full list. When a procedure returns + multiple values, this is shown by listing the return values in square + brackets, as well. So, for example, the procedure with signature +-<pre class=code-example> +-halts? <var>f [x init-store]</var> -> <var>[boolean integer]</var> ++</p> ++<pre class="code-example"> ++halts? <var>f [x init-store]</var> -> <var>[boolean integer]</var> + </pre> ++<p> + would take one (<var>f</var>), two (<var>f</var>, <var>x</var>) + or three (<var>f</var>, <var>x</var>, <var>init-store</var>) input parameters, + and return two values, a boolean and an integer. +- ++</p> + <p> + A parameter followed by "<code>...</code>" means zero-or-more elements. + So the procedure with the signature +-<pre class=code-example> +-sum-squares <var>x ... </var> -> <var>number</var> ++</p> ++<pre class="code-example"> ++sum-squares <var>x ... </var> -> <var>number</var> + </pre> ++<p> + takes zero or more arguments (<var>x ...</var>), + while the procedure with signature +-<pre class=code-example> +-spell-check <var>doc dict<sub>1</sub> dict<sub>2</sub> ...</var> -> <var>string-list</var> ++</p> ++<pre class="code-example"> ++spell-check <var>doc dict<sub>1</sub> dict<sub>2</sub> ...</var> -> <var>string-list</var> + </pre> ++<p> + takes two required parameters + (<var>doc</var> and <var>dict<sub>1</sub></var>) + and zero or more optional parameters (<var>dict<sub>2</sub> ...</var>). +- ++</p> + <p> + If a procedure is said to return "unspecified," this means that nothing at + all is said about what the procedure returns. Such a procedure is not even +@@ -901,176 +960,207 @@ Note that in + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>, + this restricts such a procedure to returning a single value; + non-R5RS systems may not even provide this restriction. +- ++</p> + <!--========================================================================--> +-<h2><a name="MainProcs">Main procedures</a></h2> ++<h3 id="MainProcs">Main procedures</h3> + + <p> + In a Scheme system that has a module or package system, these procedures + should be contained in a module named "string-lib". +- ++</p> + <!--========================================================================--> +-<h3><a name="Predicates">Predicates</a></h3> ++<h4 id="Predicates">Predicates</h4> + + <dl> + <!-- + ==== string? + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-p"></a> +-<code class=proc-def>string?</code><var> obj -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">string?</code><var> obj -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns <code>#t</code> if <var>obj</var> is a string, otherwise returns <code>#f</code>. +- ++</p> ++</dd> + <!-- + ==== string-null? + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-null-p"></a> +-<code class=proc-def>string-null?</code><var> s -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">string-null?</code><var> s -> boolean</var> ++</dt> ++<dd class="proc-def"> + Is <var>s</var> the empty string? + </dd> + + <!-- + ==== string-every string-any + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-every"></a> + <a name="string-any"></a> +-<code class=proc-def>string-every</code><var> char/char-set/pred s [start end] -> value</var> +-<dt class=proc-defn><code class=proc-def>string-any</code><var> char/char-set/pred s [start end] -> value</var> +-<dd class=proc-def> ++<code class="proc-def">string-every</code><var> char/char-set/pred s [start end] -> value</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-any</code><var> char/char-set/pred s [start end] -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + Checks to see if the given criteria is true of every / any character in <var>s</var>, + proceeding from left (index <var>start</var>) to right (index <var>end</var>). +- ++</p> + <p> + If <var>char/char-set/pred</var> is a character, it is tested for equality with + the elements of <var>s</var>. +- ++</p> + <p> + If <var>char/char-set/pred</var> is a character set, the elements of <var>s</var> are tested + for membership in the set. +- ++</p> + <p> + If <var>char/char-set/pred</var> is a predicate procedure, it is applied to the + elements of <var>s</var>. The predicate is "witness-generating:" +- ++</p> + <ul> + <li> If <code>string-any</code> returns true, the returned true value is the one produced + by the application of the predicate. +- ++ </li> + <li> If <code>string-every</code> returns true, the returned true value is the one +- produced by the final application of the predicate to <var>s</var>[<var>end</var>]. ++ produced by the final application of the predicate to <var>s</var>[<var>end</var>-1]. + If <code>string-every</code> is applied to an empty sequence of characters, + it simply returns <code>#t</code>. ++ </li> + </ul> ++<p> + If <code>string-every</code> or <code>string-any</code> apply the predicate to the final element + of the selected sequence (<em>i.e.</em>, <var>s</var>[<var>end</var>-1]), that final application is a + tail call. +- ++</p> + <p> + The names of these procedures do not end with a question mark -- this is to + indicate that, in the predicate case, they do not return a simple boolean + (<code>#t</code> or <code>#f</code>), but a general value. ++</p> ++</dd> + </dl> + + + <!--========================================================================--> +-<h3><a name="Constructors">Constructors</a></h3> ++<h4 id="Constructors">Constructors</h4> + + <dl> + <!-- + ==== make-string + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="make-string"></a> +-<code class=proc-def>make-string</code> <var>len [char] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">make-string</code> <var>len [char] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + <code>make-string</code> returns a newly allocated string of length <var>len</var>. If + <var>char</var> is given, then all elements of the string are initialized + to <var>char</var>, otherwise the contents of the string are unspecified. +- ++</p> ++</dd> + <!-- + ==== string + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string"></a> +-<code class=proc-def>string</code><var> char<sub>1</sub> ... -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string</code><var> char<sub>1</sub> ... -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns a newly allocated string composed of the argument characters. +- ++</p> ++</dd> + <!-- + ==== string-tabulate + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-tabulate"></a> +-<code class=proc-def>string-tabulate</code><var> proc len -> string</var> +-<dd class=proc-def> +- <var>Proc</var> is an integer->char procedure. Construct a string of size <var>len</var> ++<code class="proc-def">string-tabulate</code><var> proc len -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <var>Proc</var> is an integer->char procedure. Construct a string of size <var>len</var> + by applying <var>proc</var> to each index to produce the corresponding string + element. The order in which <var>proc</var> is applied to the indices is not + specified. +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h3><a name="List2String">List & string conversion</a></h3> ++<h4 id="List2String">List & string conversion</h4> + + <dl> + + <!-- + ==== string->list list->string + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string2list"></a> + <a name="list2string"></a> +-<code class=proc-def>string->list</code><var> s [start end] -> char-list</var> +-<dt class=proc-defn><code class=proc-def>list->string</code><var> char-list -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string->list</code><var> s [start end] -> char-list</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">list->string</code><var> char-list -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] +- <code>string->list</code> returns a newly allocated list of the characters +- that make up the given string. <code>list->string</code> returns a newly ++ <code>string->list</code> returns a newly allocated list of the characters ++ that make up the given string. <code>list->string</code> returns a newly + allocated string formed from the characters in the list <var>char-list</var>, +- which must be a list of characters. <code>string->list</code> and <code>list->string</code> ++ which must be a list of characters. <code>string->list</code> and <code>list->string</code> + are inverses so far as <code>equal?</code> is concerned. +- +- <p> +- <code>string->list</code> is extended from the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> definition to take optional ++</p> ++<p> ++ <code>string->list</code> is extended from the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> definition to take optional + <var>start/end</var> arguments. +- ++</p> ++</dd> + <!-- + ==== reverse-list->string + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="reverse-list2string"></a> +-<code class=proc-def>reverse-list->string</code><var> char-list -> string</var> +-<dd class=proc-def> +- An efficient implementation of <code>(compose list->string reverse)</code>: +-<pre class=code-example> +-(reverse-list->string '(#\a #\B #\c)) -> "cBa" ++<code class="proc-def">reverse-list->string</code><var> char-list -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ An efficient implementation of <code>(compose list->string reverse)</code>: ++</p> ++<pre class="code-example"> ++(reverse-list->string '(#\a #\B #\c)) -> "cBa" + </pre> ++<p> + This is a common idiom in the epilog of string-processing loops + that accumulate an answer in a reverse-order list. (See also + <code>string-concatenate-reverse</code> for the "chunked" variant.) +- ++</p> ++</dd> + <!-- + ==== string-join + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-join"></a> +-<code class=proc-def>string-join</code><var> string-list [delimiter grammar] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-join</code><var> string-list [delimiter grammar] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + This procedure is a simple unparser --- it pastes strings together using + the delimiter string. +- +- <p> ++</p> ++<p> + The <var>grammar</var> argument is a symbol that determines how the delimiter is + used, and defaults to <code>'infix</code>. +- ++</p> + <ul> + <li> <code>'infix</code> means an infix or separator grammar: + insert the delimiter +@@ -1079,20 +1169,25 @@ Returns <code>#t</code> if <var>obj</var> is a string, otherwise returns <code># + grammar is ambiguous. Is it an empty list, or a list of one element, + the empty string? + +- <li> <code>'strict-infix</code> means the same as <code>'infix</code>, ++ </li> ++ <li> <code>'strict-infix</code> means the same as <code>'infix</code>, + but will raise an error if given an empty list. + ++ </li> + <li> <code>'suffix</code> means a suffix or terminator grammar: + insert the delimiter + after every list element. This grammar has no ambiguities. + ++ </li> + <li> <code>'prefix</code> means a prefix grammar: insert the delimiter + before every list element. This grammar has no ambiguities. ++ </li> + </ul> +- ++<p> + The delimiter is the string used to delimit elements; it defaults to + a single space " ". +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-join '("foo" "bar" "baz") ":") => "foo:bar:baz" + (string-join '("foo" "bar" "baz") ":" 'suffix) => "foo:bar:baz:" + +@@ -1104,103 +1199,124 @@ Returns <code>#t</code> if <var>obj</var> is a string, otherwise returns <code># + (string-join '() ":" 'suffix) => "" + (string-join '("") ":" 'suffix) => ":" + </pre> ++</dd> + </dl> + + + <!--========================================================================--> +-<h3><a name="Selection">Selection</a></h3> ++<h4 id="Selection">Selection</h4> + + <dl> + <!-- + ==== string-length + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-length"></a> +-<code class=proc-def>string-length</code><var> s -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">string-length</code><var> s -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns the number of characters in the string <var>s</var>. +- ++</p> ++</dd> + <!-- + ==== string-ref + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-ref"></a> +-<code class=proc-def>string-ref</code><var> s i -> char</var> +-<dd class=proc-def> ++<code class="proc-def">string-ref</code><var> s i -> char</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns character <var>s[i]</var> using zero-origin indexing. + <var>I</var> must be a valid index of <var>s</var>. +- ++</p> ++</dd> + <!-- + ==== string-copy substring/shared + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-copy"></a> + <a name="substring/shared"></a> +-<code class=proc-def>string-copy</code><var> s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>substring/shared</code><var> s start [end] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-copy</code><var> s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">substring/shared</code><var> s start [end] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] + <code>substring/shared</code> returns a string whose contents are the characters of <var>s</var> + beginning with index <var>start</var> (inclusive) and ending with index <var>end</var> + (exclusive). It differs from the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> <code>substring</code> in two ways: ++</p> + <ul> + <li> The <var>end</var> parameter is optional, not required. ++ </li> + <li> <code>substring/shared</code> may return a value that shares memory with <var>s</var> or + is <code>eq?</code> to <var>s</var>. ++ </li> + </ul> +- +- <p> ++<p> + <code>string-copy</code> is extended from its <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> definition by the addition of + its optional <var>start/end</var> parameters. In contrast to <code>substring/shared</code>, + it is guaranteed to produce a freshly-allocated string. +- +- <p> ++</p> ++<p> + Use <code>string-copy</code> when you want to indicate explicitly in your code that you + wish to allocate new storage; use <code>substring/shared</code> when you don't care if + you get a fresh copy or share storage with the original string. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-copy "Beta substitution") => "Beta substitution" + (string-copy "Beta substitution" 1 10) + => "eta subst" + (string-copy "Beta substitution" 5) => "substitution" + </pre> +- ++</dd> + <!-- + ==== string-copy! + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-copy!"></a> +-<code class=proc-def>string-copy!</code><var> target tstart s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-copy!</code><var> target tstart s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++ <p> + Copy the sequence of characters from index range [<var>start</var>,<var>end</var>) in + string <var>s</var> to string <var>target</var>, beginning at index <var>tstart</var>. The characters + are copied left-to-right or right-to-left as needed -- the copy is + guaranteed to work, even if <var>target</var> and <var>s</var> are the same string. +- ++ </p> + <p> + It is an error if the copy operation runs off the end of the target + string, <em>e.g.</em> +-<pre class=code-example> ++ </p> ++<pre class="code-example"> + (string-copy! (string-copy "Microsoft") 0 + "Regional Microsoft Operating Companies") => <em>error</em> + </pre> +- ++</dd> + + <!-- + ==== string-take string-drop string-take-right string-drop-right + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-take"></a> + <a name="string-drop"></a> + <a name="string-take-right"></a> + <a name="string-drop-right"></a> +-<code class=proc-def>string-take</code><var> s nchars -> string</var> +-<dt class=proc-defi><code class=proc-def>string-drop</code><var> s nchars -> string</var> +-<dt class=proc-defi><code class=proc-def>string-take-right</code><var> s nchars -> string</var> +-<dt class=proc-defn><code class=proc-def>string-drop-right</code><var> s nchars -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-take</code><var> s nchars -> string</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-drop</code><var> s nchars -> string</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-take-right</code><var> s nchars -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-drop-right</code><var> s nchars -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>string-take</code> returns the first <var>nchars</var> of <var>s</var>; + <code>string-drop</code> returns all but the first <var>nchars</var> of <var>s</var>. + <code>string-take-right</code> returns the last <var>nchars</var> of <var>s</var>; +@@ -1208,133 +1324,157 @@ Returns <code>#t</code> if <var>obj</var> is a string, otherwise returns <code># + If these procedures produce the entire string, they may return either + <var>s</var> or a copy of <var>s</var>; in some implementations, proper substrings may share + memory with <var>s</var>. +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-take "Pete Szilagyi" 6) => "Pete S" + (string-drop "Pete Szilagyi" 6) => "zilagyi" + + (string-take-right "Beta rules" 5) => "rules" + (string-drop-right "Beta rules" 5) => "Beta " + </pre> +- ++<p> + It is an error to take or drop more characters than are in the string: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-take "foo" 37) => <em>error</em> + </pre> +- ++</dd> + <!-- + ==== string-pad string-pad-right + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-pad"></a> + <a name="string-pad-right"></a> +-<code class=proc-def>string-pad</code><var> s len [char start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-pad-right</code><var> s len [char start end] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-pad</code><var> s len [char start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-pad-right</code><var> s len [char start end] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + Build a string of length <var>len</var> comprised of <var>s</var> padded on the left (right) + by as many occurrences of the character <var>char</var> as needed. If <var>s</var> has more + than <var>len</var> chars, it is truncated on the left (right) to length <var>len</var>. <var>Char</var> + defaults to #\space. +- +- <p> ++</p> ++<p> + If <var>len</var> <= <var>end</var>-<var>start</var>, the returned value is allowed to share storage + with <var>s</var>, or be exactly <var>s</var> (if <var>len</var> = <var>end</var>-<var>start</var>). +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-pad "325" 5) => " 325" + (string-pad "71325" 5) => "71325" + (string-pad "8871325" 5) => "71325" + </pre> +- ++</dd> + <!-- + ==== string-trim string-trim-right string-trim-both + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-trim"></a> + <a name="string-trim-right"></a> + <a name="string-trim-both"></a> +-<code class=proc-def>string-trim </code><var> s [char/char-set/pred start end] -> string</var> +-<dt class=proc-defi><code class=proc-def>string-trim-right</code><var> s [char/char-set/pred start end] -> string</var> +-<dt class=proc-defi><code class=proc-def>string-trim-both </code><var> s [char/char-set/pred start end] -> string</var> +-<dd class=proc-defn> ++<code class="proc-def">string-trim </code><var> s [char/char-set/pred start end] -> string</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-trim-right</code><var> s [char/char-set/pred start end] -> string</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-trim-both </code><var> s [char/char-set/pred start end] -> string</var> ++</dt> ++<dd class="proc-defn"> ++<p> + Trim <var>s</var> by skipping over all characters on the left / on the right / + on both sides that satisfy the second parameter <var>char/char-set/pred</var>: +- <ul> ++</p> ++<ul> + <li> if it is a character <var>char</var>, characters equal to <var>char</var> are trimmed; ++ </li> + <li> if it is a char set <var>cs</var>, characters contained in <var>cs</var> are trimmed; ++ </li> + <li> if it is a predicate <var>pred</var>, it is a test predicate that is applied + to the characters in <var>s</var>; a character causing it to return true + is skipped. +- </ul> ++ </li> ++</ul> ++<p> + <var>Char/char-set/pred</var> defaults to the character set <code>char-set:whitespace</code> + defined in <a href="#SRFI-14">SRFI 14</a>. +- +- <p> ++</p> ++<p> + If no trimming occurs, these functions may return either <var>s</var> or a copy of <var>s</var>; + in some implementations, proper substrings may share memory with <var>s</var>. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-trim-both " The outlook wasn't brilliant, \n\r") + => "The outlook wasn't brilliant," + </pre> ++</dd> + </dl> + + + <!--========================================================================--> +-<h3><a name="Modification">Modification</a></h3> ++<h4 id="Modification">Modification</h4> + + <dl> + + <!-- + ==== string-set! + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-set!"></a> +-<code class=proc-def>string-set!</code><var> s i char -> unspecified </var> +-<dd class=proc-def> ++<code class="proc-def">string-set!</code><var> s i char -> unspecified </var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + <var>I</var> must be a valid index of <var>s</var>. <code>string-set!</code> stores <var>char</var> in + element <var>i</var> of <var>s</var>. Constant string literals appearing in code are + immutable; it is an error to use them in a <code>string-set!.</code> +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (f) (make-string 3 #\*)) + (define (g) "***") + (string-set! (f) 0 #\?) ==> <em>unspecified</em> + (string-set! (g) 0 #\?) ==> <em>error</em> +-(string-set! (symbol->string 'immutable) ++(string-set! (symbol->string 'immutable) + 3 + #\?) ==> <em>error</em> + </pre> +- ++</dd> + <!-- + ==== string-fill! + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-fill!"></a> +-<code class=proc-def>string-fill!</code><var> s char [start end] -> unspecified </var> +-<dd class=proc-def> ++<code class="proc-def">string-fill!</code><var> s char [start end] -> unspecified </var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>+] + Stores <var>char</var> in every element of <var>s</var>. +- +- <p> ++</p> ++<p> + <code>string-fill</code> is extended from the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> definition to take optional + <var>start/end</var> arguments. +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h3><a name="Comparison">Comparison</a></h3> ++<h4 id="Comparison">Comparison</h4> + + <dl> + + <!-- + ==== string-compare string-compare-ci + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-compare"></a> + <a name="string-compare-ci"></a> +-<code class=proc-def>string-compare </code><var> s1 s2 proc< proc= proc> [start1 end1 start2 end2] -> values</var> +-<dt class=proc-defi><code class=proc-def>string-compare-ci</code><var> s1 s2 proc< proc= proc> [start1 end1 start2 end2] -> values</var> +-<dd class=proc-defn> ++<code class="proc-def">string-compare </code><var> s1 s2 proc< proc= proc> [start1 end1 start2 end2] -> values</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-compare-ci</code><var> s1 s2 proc< proc= proc> [start1 end1 start2 end2] -> values</var> ++</dt> ++<dd class="proc-defn"> ++<p> + Apply <var>proc<</var>, <var>proc=</var>, or <var>proc></var> + to the mismatch index, depending + upon whether <var>s1</var> is less than, equal to, or greater than <var>s2</var>. +@@ -1342,156 +1482,182 @@ The "mismatch index" is the largest index <var>i</var> such that for + every 0 <= <var>j</var> < <var>i</var>, + <var>s1[j]</var> = <var>s2[j]</var> + -- that is, <var>i</var> is the first position that doesn't match. +- ++</p> + <p> + <code>string-compare-ci</code> is the case-insensitive variant. Case-insensitive + comparison is done by case-folding characters with the operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase <var>c</var>)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- + <p> + The optional start/end indices restrict the comparison to the indicated + substrings of <var>s1</var> and <var>s2</var>. The mismatch index is always an index into <var>s1</var>; + in the case of <var>proc=</var>, it is always <var>end1</var>; + we observe the protocol + in this redundant case for uniformity. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-compare "The cat in the hat" "abcdefgh" + values values values + 4 6 ; Select "ca" + 2 4) ; & "cd" + => 5 ; Index of S1's "a" + </pre> +- ++<p> + Comparison is simply done on individual code-points of the string. + True text collation is not handled by this SRFI. +- ++</p> ++</dd> + <!-- + ==== string= string<> string< string> string<= string>= + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string="></a> +-<a name="string<>"></a> +-<a name="string<"></a> +-<a name="string>"></a> +-<a name="string<="></a> +-<a name="string>="></a> +-<code class=proc-def>string= </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string<></code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string< </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string> </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string<=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defn><code class=proc-def>string>=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dd class=proc-def> ++<a name="string<>"></a> ++<a name="string<"></a> ++<a name="string>"></a> ++<a name="string<="></a> ++<a name="string>="></a> ++<code class="proc-def">string= </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string<></code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string< </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string> </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string<=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string>=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + These procedures are the lexicographic extensions to strings of the + corresponding orderings on characters. For example, <code>string<</code> is the + lexicographic ordering on strings induced by the ordering <code>char<?</code> on + characters. If two strings differ in length but are the same up to + the length of the shorter string, the shorter string is considered to + be lexicographically less than the longer string. +- +- <p> ++</p> ++<p> + The optional start/end indices restrict the comparison to the indicated + substrings of <var>s1</var> and <var>s2</var>. +- +- <p> ++</p> ++<p> + Comparison is simply done on individual code-points of the string. + True text collation is not handled by this SRFI. +- ++</p> ++</dd> + <!-- + ==== string-ci= string-ci<> string-ci< string-ci> string-ci<= string-ci>= + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-ci="></a> +-<a name="string-ci<>"></a> +-<a name="string-ci<"></a> +-<a name="string-ci>"></a> +-<a name="string-ci<="></a> +-<a name="string-ci>="></a> +-<code class=proc-def>string-ci= </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-ci<></code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-ci< </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-ci> </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-ci<=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defn><code class=proc-def>string-ci>=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dd class=proc-def> ++<a name="string-ci<>"></a> ++<a name="string-ci<"></a> ++<a name="string-ci>"></a> ++<a name="string-ci<="></a> ++<a name="string-ci>="></a> ++<code class="proc-def">string-ci= </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-ci<></code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-ci< </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-ci> </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-ci<=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-ci>=</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Case-insensitive variants. +- +- <p> ++</p> ++<p> + Case-insensitive comparison is done by case-folding characters with + the operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase <var>c</var>)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- ++</dd> + <!-- + ==== string-hash string-hash-ci + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-hash"></a> + <a name="string-hash-ci"></a> +-<code class=proc-def>string-hash </code><var> s [bound start end] -> integer</var> +-<dt class=proc-defn><code class=proc-def>string-hash-ci</code><var> s [bound start end] -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">string-hash </code><var> s [bound start end] -> integer</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-hash-ci</code><var> s [bound start end] -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Compute a hash value for the string <var>s</var>. + <var>Bound</var> is a non-negative + exact integer specifying the range of the hash function. A positive + value restricts the return value to the range [0,<var>bound</var>). +- ++</p> + <p> + If <var>bound</var> is either zero or not given, the implementation may use + an implementation-specific default value, chosen to be as large as + is efficiently practical. For instance, the default range might be chosen + for a given implementation to map all strings into the range of + integers that can be represented with a single machine word. +- ++</p> + <p> + The optional start/end indices restrict the hash operation to the + indicated substring of <var>s</var>. +- ++</p> + <p> + <code>string-hash-ci</code> is the case-insensitive variant. Case-insensitive + comparison is done by case-folding characters with the operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase <var>c</var>)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt"> + ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- + <p> + Invariants: +-<pre class=code-example> +-(<= 0 (string-hash s b) (- b 1)) ; When B > 0. ++</p> ++<pre class="code-example"> ++(<= 0 (string-hash s b) (- b 1)) ; When B > 0. + (string= s1 s2) => (= (string-hash s1 b) (string-hash s2 b)) + (string-ci= s1 s2) => (= (string-hash-ci s1 b) (string-hash-ci s2 b)) + </pre> +- + <p> + A legal but nonetheless discouraged implementation: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (string-hash s . other-args) 1) + (define (string-hash-ci s . other-args) 1) + </pre> +- + <p> + Rationale: allowing the user to specify an explicit bound simplifies user + code by removing the mod operation that typically accompanies every hash +@@ -1502,231 +1668,274 @@ A legal but nonetheless discouraged implementation: + intermediate values never overflow into bignum integers, allowing the + implementor to provide a fixnum-specific "fast path" for computing the + common cases very rapidly. +- +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h3><a name="PrefixesSuffixes">Prefixes & suffixes</a></h3> ++<h4 id="PrefixesSuffixes">Prefixes & suffixes</h4> + + <dl> + <!-- + ==== string-prefix-length string-suffix-length + ==== string-prefix-length-ci string-suffix-length-ci + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-prefix-length"></a> + <a name="string-suffix-length"></a> + <a name="string-prefix-length-ci"></a> + <a name="string-suffix-length-ci"></a> +-<code class=proc-def>string-prefix-length </code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> +-<dt class=proc-defi><code class=proc-def>string-suffix-length </code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> +-<dt class=proc-defi><code class=proc-def>string-prefix-length-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> +-<dt class=proc-defn><code class=proc-def>string-suffix-length-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">string-prefix-length </code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-suffix-length </code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-prefix-length-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-suffix-length-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return the length of the longest common prefix/suffix of the two strings. + For prefixes, this is equivalent to the "mismatch index" for the strings + (modulo the <var>start</var>i index offsets). +- ++</p> + <p> + The optional start/end indices restrict the comparison to the indicated + substrings of <var>s1</var> and <var>s2</var>. +- ++</p> + <p> + <code>string-prefix-length-ci</code> and <code>string-suffix-length-ci</code> are the + case-insensitive variants. Case-insensitive comparison is done by + case-folding characters with the operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase c)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> ++<p> + Comparison is simply done on individual code-points of the string. +- ++</p> ++</dd> + <!-- + ==== string-prefix? string-suffix? string-prefix-ci? string-suffix-ci? + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-prefix-p"></a> + <a name="string-suffix-p"></a> + <a name="string-prefix-ci-p"></a> + <a name="string-suffix-ci-p"></a> +-<code class=proc-def>string-prefix? </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-suffix? </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defi><code class=proc-def>string-prefix-ci?</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dt class=proc-defn><code class=proc-def>string-suffix-ci?</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">string-prefix? </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-suffix? </code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-prefix-ci?</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-suffix-ci?</code><var> s1 s2 [start1 end1 start2 end2] -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Is <var>s1</var> a prefix/suffix of <var>s2</var>? +- ++</p> + <p> + The optional start/end indices restrict the comparison to the indicated + substrings of <var>s1</var> and <var>s2</var>. +- ++</p> + <p> + <code>string-prefix-ci?</code> and <code>string-suffix-ci?</code> are the case-insensitive variants. + Case-insensitive comparison is done by case-folding characters with the + operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase c)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- + <p> + Comparison is simply done on individual code-points of the string. +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h3><a name="Searching">Searching</a></h3> ++<h4 id="Searching">Searching</h4> + + <dl> + + <!-- + ==== string-index string-index-right string-skip string-skip-right + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-index"></a> + <a name="string-index-right"></a> + <a name="string-skip"></a> + <a name="string-skip-right"></a> +-<code class=proc-def>string-index</code><var> s char/char-set/pred [start end] -> integer or #f</var> +-<dt class=proc-defi><code class=proc-def>string-index-right</code><var> s char/char-set/pred [start end] -> integer or #f</var> +-<dt class=proc-defi><code class=proc-def>string-skip</code><var> s char/char-set/pred [start end] -> integer or #f</var> +-<dt class=proc-defn><code class=proc-def>string-skip-right</code><var> s char/char-set/pred [start end] -> integer or #f</var> +-<dd class=proc-def> ++<code class="proc-def">string-index</code><var> s char/char-set/pred [start end] -> integer or #f</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-index-right</code><var> s char/char-set/pred [start end] -> integer or #f</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-skip</code><var> s char/char-set/pred [start end] -> integer or #f</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-skip-right</code><var> s char/char-set/pred [start end] -> integer or #f</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>string-index</code> (<code>string-index-right</code>) searches through the string from the + left (right), returning the index of the first occurrence of a character + which ++</p> + <ul> + <li> equals <var>char/char-set/pred</var> (if it is a character); ++ </li> + <li> is in <var>char/char-set/pred</var> (if it is a character set); ++ </li> + <li> satisfies the predicate <var>char/char-set/pred</var> (if it is a procedure). ++ </li> + </ul> ++<p> + If no match is found, the functions return false. +- ++</p> + <p> + The <var>start</var> and <var>end</var> parameters specify the beginning and end indices of + the search; the search includes the start index, but not the end index. + Be careful of "fencepost" considerations: when searching right-to-left, + the first index considered is +-<div class=inset> ++</p> ++<div class="inset"> + <var>end</var>-1 + </div> ++<p> + whereas when searching left-to-right, the first index considered is +-<div class=inset> ++</p> ++<div class="inset"> + <var>start</var> + </div> ++<p> + That is, the start/end indices describe a same half-open interval + [<var>start</var>,<var>end</var>) in these procedures that they do + in all the other SRFI 13 procedures. +- ++</p> + <p> + The skip functions are similar, but use the complement of the criteria: + they search for the first char that <em>doesn't</em> satisfy the test. <em>E.g.</em>, + to skip over initial whitespace, say +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (cond ((string-skip s char-set:whitespace) => + (lambda (i) ...)) ; s[i] is not whitespace. + ...) + </pre> +- ++</dd> + <!-- + ==== string-count + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-count"></a> +-<code class=proc-def>string-count</code><var> s char/char-set/pred [start end] -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">string-count</code><var> s char/char-set/pred [start end] -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return a count of the number of characters in <var>s</var> that satisfy the + <var>char/char-set/pred</var> argument. If this argument is a procedure, + it is applied to the character as a predicate; if it is a character set, + the character is tested for membership; if it is a character, it is + used in an equality test. +- ++</p> ++</dd> + <!-- + ==== string-contains string-contains-ci + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-contains"></a> + <a name="string-contains-ci"></a> +-<code class=proc-def>string-contains </code><var> s1 s2 [start1 end1 start2 end2] -> integer or false</var> +-<dt class=proc-defn><code class=proc-def>string-contains-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer or false</var> +-<dd class=proc-def> ++<code class="proc-def">string-contains </code><var> s1 s2 [start1 end1 start2 end2] -> integer or false</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-contains-ci</code><var> s1 s2 [start1 end1 start2 end2] -> integer or false</var> ++</dt> ++<dd class="proc-def"> ++<p> + Does string <var>s1</var> contain string <var>s2</var>? +- ++</p> + <p> + Return the index in <var>s1</var> where <var>s2</var> occurs as a substring, or false. + The optional start/end indices restrict the operation to the + indicated substrings. +- ++</p> + <p> + The returned index is in the range [<var>start1</var>,<var>end1</var>). + A successful match must lie entirely in the + [<var>start1</var>,<var>end1</var>) range of <var>s1</var>. +- +-<p> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-contains "eek -- what a geek." "ee" + 12 18) ; Searches "a geek" + => 15 + </pre> +- + <p> + <code>string-contains-ci</code> is the case-insensitive variant. Case-insensitive + comparison is done by case-folding characters with the operation +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-downcase (char-upcase <var>c</var>)) + </pre> ++<p> + where the two case-mapping operations are assumed to be 1-1, locale- and + context-insensitive, and compatible with the 1-1 case mappings specified + by Unicode's UnicodeData.txt table: +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- + <p> + Comparison is simply done on individual code-points of the string. +- ++</p> + <p> + The names of these procedures do not end with a question mark -- this is to + indicate that they do not return a simple boolean (<code>#t</code> or <code>#f</code>). Rather, + they return either false (<code>#f</code>) or an exact non-negative integer. +- ++</p> ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h3><a name="CaseMapping">Alphabetic case mapping</a></h3> ++<h4 id="CaseMapping">Alphabetic case mapping</h4> + + <dl> + + <!-- + ==== string-titlecase string-titlecase! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-titlecase"></a> + <a name="string-titlecase!"></a> +-<code class=proc-def>string-titlecase </code><var> s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-titlecase!</code><var> s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-titlecase </code><var> s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-titlecase!</code><var> s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + For every character <var>c</var> in the selected range of <var>s</var>, + if <var>c</var> is preceded by a cased character, it is downcased; + otherwise it is titlecased. +- ++</p> + <p> + <code>string-titlecase</code> returns the result string and does not alter its <var>s</var> + parameter. <code>string-titlecase!</code> is the in-place side-effecting variant. +- +-<p> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-titlecase "--capitalize tHIS sentence.") => + "--Capitalize This Sentence." + +@@ -1736,70 +1945,80 @@ parameter. <code>string-titlecase!</code> is the in-place side-effecting variant + (string-titlecase "3com makes routers.") => + "3Com Makes Routers." + </pre> +- + <p> + Note that if a <var>start</var> index is specified, then the character + preceding <var>s</var>[<var>start</var>] has no effect on the titlecase decision for + character <var>s</var>[<var>start</var>]: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-titlecase "greasy fried chicken" 2) => "Easy Fried Chicken" + </pre> +- + <p> + Titlecase and cased information must be compatible with the Unicode + specification. +- ++</p> ++</dd> + <!-- + ==== string-upcase string-upcase! string-downcase string-downcase! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-upcase"></a> + <a name="string-upcase!"></a> + <a name="string-downcase"></a> + <a name="string-downcase!"></a> +-<code class=proc-def>string-upcase </code><var> s [start end] -> string</var> +-<dt class=proc-defi><code class=proc-def>string-upcase!</code><var> s [start end] -> unspecified</var> +-<dt class=proc-defi><code class=proc-def>string-downcase </code><var> s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-downcase!</code><var> s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-upcase </code><var> s [start end] -> string</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-upcase!</code><var> s [start end] -> unspecified</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">string-downcase </code><var> s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-downcase!</code><var> s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Raise or lower the case of the alphabetic characters in the string. +- +- <p> ++</p> ++<p> + <code>string-upcase</code> and <code>string-downcase</code> return the result string and do not + alter their <var>s</var> parameter. <code>string-upcase!</code> and <code>string-downcase!</code> are the +- in-place side-effecting variants. +- +- <p> ++ in-place side-effecting variants. ++</p> ++<p> + These procedures use the locale- and context-insensitive 1-1 case mappings + defined by Unicode's UnicodeData.txt table: +- <div class=inset> ++</p> ++ <div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +- ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h3><a name="ReverseAppend">Reverse & append</a></h3> ++<h4 id="ReverseAppend">Reverse & append</h4> + + <dl> + + <!-- + ==== string-reverse string-reverse! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-reverse"></a> + <a name="string-reverse!"></a> +-<code class=proc-def>string-reverse </code><var> s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-reverse!</code><var> s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-reverse </code><var> s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-reverse!</code><var> s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Reverse the string. +- ++</p> + <p> + <code>string-reverse</code> returns the result string + and does not alter its <var>s</var> parameter. + <code>string-reverse!</code> is the in-place side-effecting variant. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-reverse "Able was I ere I saw elba.") + => ".able was I ere I saw elbA" + +@@ -1810,49 +2029,58 @@ and does not alter its <var>s</var> parameter. + (string-reverse! s i) + (string-reverse! s))) + </pre> +- + <p> + Unicode note: Reversing a string simply reverses the sequence of + code-points it contains. So a zero-width accent character <var>a</var> + coming <em>after</em> a base character <var>b</var> in string <var>s</var> + would come out <em>before</em> <var>b</var> in the reversed result. +- ++</p> ++</dd> + <!-- + ==== string-append + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-append"></a> +-<code class=proc-def>string-append</code><var> s<sub>1</sub> ... -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-append</code><var> s<sub>1</sub> ... -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + [<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>] + Returns a newly allocated string whose characters form the + concatenation of the given strings. +- ++</p> ++</dd> + <!-- + ==== string-concatenate + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-concatenate"></a> +-<code class=proc-def>string-concatenate</code><var> string-list -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-concatenate</code><var> string-list -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + Append the elements of <code>string-list</code> together into a single string. + Guaranteed to return a freshly allocated string. +- +- <p> ++</p> ++<p> + Note that the <code>(apply string-append <var>string-list</var>)</code> + idiom is + not robust for long lists of strings, as some Scheme implementations + limit the number of arguments that may be passed to an n-ary procedure. +- ++</p> ++</dd> + <!-- + ==== string-concatenate/shared string-append/shared + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-concatenate/shared"></a> + <a name="string-append/shared"></a> +-<code class=proc-def>string-concatenate/shared</code><var> string-list -> string</var> +-<dt class=proc-defn><code class=proc-def>string-append/shared</code><var> s<sub>1</sub> ... -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-concatenate/shared</code><var> string-list -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-append/shared</code><var> s<sub>1</sub> ... -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + These two procedures are variants of <code>string-concatenate</code> + and <code>string-append</code> + that are permitted to return results that share storage with their +@@ -1860,122 +2088,146 @@ would come out <em>before</em> <var>b</var> in the reversed result. + In particular, if <code>string-append/shared</code> is applied to just + one argument, it may return exactly that argument, + whereas <code>string-append</code> is required to allocate a fresh string. +- ++</p> ++</dd> + <!-- + ==== string-concatenate-reverse string-concatenate-reverse/shared + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-concatenate-reverse"></a> + <a name="string-concatenate-reverse/shared"></a> +-<code class=proc-def>string-concatenate-reverse</code><var> string-list [final-string end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-concatenate-reverse/shared</code><var> string-list [final-string end] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-concatenate-reverse</code><var> string-list [final-string end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-concatenate-reverse/shared</code><var> string-list [final-string end] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + With no optional arguments, these functions are equivalent to +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-concatenate (reverse <var>string-list</var>)) + </pre> ++<p> + and +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-concatenate/shared (reverse <var>string-list</var>)) + </pre> ++<p> + respectively. +- ++</p> + <p> + If the optional argument <var>final-string</var> is specified, it is consed + onto the beginning of <var>string-list</var> + before performing the list-reverse and string-concatenate operations. +- + </p> ++<p> + If the optional argument <var>end</var> is given, + only the first <var>end</var> characters + of <var>final-string</var> are added to the string list, thus producing +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-concatenate + (reverse (cons (substring/shared <var>final-string</var> 0 <var>end</var>) + <var>string-list</var>))) + </pre> ++<p> + <em>E.g.</em> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-concatenate-reverse '(" must be" "Hello, I") " going.XXXX" 7) + => "Hello, I must be going." + </pre> +- + <p> + This procedure is useful in the construction of procedures that + accumulate character data into lists of string buffers, and wish to + convert the accumulated data into a single string when done. +- ++</p> + <p> + Unicode note: Reversing a string simply reverses the sequence of + code-points it contains. + So a zero-width accent character <var>ac</var> coming <em>after</em> + a base character <var>bc</var> in string <var>s</var> would come out + <em>before</em> <var>bc</var> in the reversed result. +- ++</p> ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h3><a name="FoldUnfoldMap">Fold, unfold & map</a></h3> ++<h4 id="FoldUnfoldMap">Fold, unfold & map</h4> + + <dl> + + <!-- + ==== string-map string-map! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-map"></a> + <a name="string-map!"></a> +-<code class=proc-def>string-map </code><var> proc s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-map!</code><var> proc s [start end] -> unspecified</var> +-<dd class=proc-def> +- <var>Proc</var> is a char->char procedure; it is mapped over <var>s</var>. +- +- <p> ++<code class="proc-def">string-map </code><var> proc s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-map!</code><var> proc s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <var>Proc</var> is a char->char procedure; it is mapped over <var>s</var>. ++</p> ++<p> + <code>string-map</code> returns the result string and does not alter its <var>s</var> parameter. + <code>string-map!</code> is the in-place side-effecting variant. +- +- <p> ++</p> ++<p> + Note: The order in which <var>proc</var> is applied to the elements of + <var>s</var> is not specified. +- ++</p> ++</dd> + <!-- + ==== string-fold string-fold-right + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-fold"></a> + <a name="string-fold-right"></a> +-<code class=proc-def>string-fold</code><var> kons knil s [start end] -> value</var> +-<dt class=proc-defn><code class=proc-def>string-fold-right</code><var> kons knil s [start end] -> value</var> +-<dd class=proc-def> ++<code class="proc-def">string-fold</code><var> kons knil s [start end] -> value</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-fold-right</code><var> kons knil s [start end] -> value</var> ++</dt> ++<dd class="proc-def"> ++<p> + These are the fundamental iterators for strings. +- ++</p> + <p> + The left-fold operator maps the <var>kons</var> procedure across the + string from left to right +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (... (<var>kons</var> <var>s</var>[2] (<var>kons</var> <var>s</var>[1] (<var>kons</var> <var>s</var>[0] <var>knil</var>)))) + </pre> ++<p> + In other words, <code>string-fold</code> obeys the (tail) recursion +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-fold <var>kons</var> <var>knil</var> <var>s</var> <var>start</var> <var>end</var>) = + (string-fold <var>kons</var> (<var>kons</var> <var>s</var>[<var>start</var>] <var>knil</var>) <var>start+1</var> <var>end</var>) + </pre> +- + <p> + The right-fold operator maps the <var>kons</var> procedure across the + string from right to left +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (<var>kons</var> <var>s</var>[0] (... (<var>kons</var> <var>s</var>[<var>end-3</var>] (<var>kons</var> <var>s</var>[<var>end-2</var>] (<var>kons</var> <var>s</var>[<var>end-1</var>] <var>knil</var>))))) + </pre> ++<p> + obeying the (tail) recursion +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-fold-right <var>kons</var> <var>knil</var> <var>s</var> <var>start</var> <var>end</var>) = + (string-fold-right <var>kons</var> (<var>kons</var> <var>s</var>[<var>end-1</var>] <var>knil</var>) <var>start</var> <var>end-1</var>) + </pre> +- + <p> + Examples: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;;; Convert a string to a list of chars. + (string-fold-right cons '() s) + +@@ -2001,39 +2253,46 @@ Examples: + 0 s) + ans) + </pre> +- + <p> + The right-fold combinator is sometimes called a "catamorphism." +- ++</p> ++</dd> + <!-- + ==== string-unfold + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-unfold"></a> +-<code class=proc-def>string-unfold</code><var> p f g seed [base make-final] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-unfold</code><var> p f g seed [base make-final] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + This is a fundamental constructor for strings. ++</p> + <ul> + <li> <var>G</var> is used to generate a series of "seed" values from the initial seed: +-<div class=inset> ++<div class="inset"> + <var>seed</var>, (<var>g</var> <var>seed</var>), (<var>g<sup>2</sup></var> <var>seed</var>), (<var>g<sup>3</sup></var> <var>seed</var>), ... + </div> ++</li> + <li> <var>P</var> tells us when to stop -- when it returns true when applied to one + of these seed values. ++</li> + <li> <var>F</var> maps each seed value to the corresponding character + in the result string. These chars are assembled into the + string in a left-to-right order. ++</li> + <li> <var>Base</var> is the optional initial/leftmost portion of the constructed string; + it defaults to the empty string "". ++</li> + <li> <var>Make-final</var> is applied to the terminal seed value (on which <var>p</var> returns + true) to produce the final/rightmost portion of the constructed string. + It defaults to <code>(lambda (x) "")</code>. ++</li> + </ul> +- + <p> + More precisely, the following (simple, inefficient) definitions hold: +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;;; Iterative + (define (string-unfold p f g seed base make-final) + (let lp ((seed seed) (ans base)) +@@ -2053,18 +2312,20 @@ More precisely, the following (simple, inefficient) definitions hold: + <code>string-unfold</code> is a fairly powerful string constructor -- you can use it to + convert a list to a string, read a port into a string, reverse a string, + copy a string, and so forth. Examples: +-<pre class=code-example> +-(port->string p) = (string-unfold eof-object? values ++</p> ++<pre class="code-example"> ++(port->string p) = (string-unfold eof-object? values + (lambda (x) (read-char p)) + (read-char p)) + +-(list->string lis) = (string-unfold null? car cdr lis) ++(list->string lis) = (string-unfold null? car cdr lis) + + (string-tabulate f size) = (string-unfold (lambda (i) (= i size)) f add1 0) + </pre> + <p> + To map <var>f</var> over a list <var>lis</var>, producing a string: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-unfold null? (compose f car) cdr lis) + </pre> + <p> +@@ -2072,56 +2333,70 @@ Interested functional programmers may enjoy noting that + <code>string-fold-right</code> + and <code>string-unfold</code> are in some sense inverses. That is, given operations + <var>knull?</var>, <var>kar</var><var>, kdr</var>, <var>kons</var>, and <var>knil</var> satisfying +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (<var>kons</var> (<var>kar</var> x) (<var>kdr</var> x)) = x and (<var>knull?</var> <var>knil</var>) = #t + </pre> ++<p> + then +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-fold-right <var>kons</var> <var>knil</var> (string-unfold <var>knull?</var> <var>kar</var> <var>kdr</var> <var>x</var>)) = <var>x</var> + </pre> ++<p> + and +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-unfold <var>knull?</var> <var>kar</var> <var>kdr</var> (string-fold-right <var>kons</var> <var>knil</var> <var>s</var>)) = <var>s</var>. + </pre> +- ++<p> + The final string constructed does not share storage with either <var>base</var> + or the value produced by <var>make-final</var>. +- ++</p> + <p> + This combinator sometimes is called an "anamorphism." +- ++</p> + <p> + Note: implementations should take care that runtime stack limits do not + cause overflow when constructing large (<em>e.g.</em>, megabyte) strings with + <code>string-unfold</code>. +- ++</p> ++</dd> + + <!-- + ==== string-unfold-right + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-unfold-right"></a> +-<code class=proc-def>string-unfold-right</code><var> p f g seed [base make-final] -> string</var> +-<dd class=proc-def> +- This is a fundamental constructor for strings. ++<code class="proc-def">string-unfold-right</code><var> p f g seed [base make-final] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ This is a fundamental constructor for strings. ++</p> + <ul> + <li> <var>G</var> is used to generate a series of "seed" values from the initial seed: + <var>seed</var>, (<var>g</var> <var>seed</var>), (<var>g<sup>2</sup></var> <var>seed</var>), (<var>g<sup>3</sup></var> <var>seed</var>), ... ++ </li> + <li> <var>P</var> tells us when to stop -- when it returns true when applied to one + of these seed values. ++ </li> + <li> <var>F</var> maps each seed value to the corresponding character + in the result string. These chars are assembled into the + string in a right-to-left order. ++ </li> + <li> <var>Base</var> is the optional initial/rightmost portion of the constructed string; + it defaults to the empty string "". ++ </li> + <li> <var>Make-final</var> is applied to the terminal seed value (on which <var>P</var> returns + true) to produce the final/leftmost portion of the constructed string. + It defaults to <code>(lambda (x) "")</code>. ++ </li> + </ul> +- +- <p> ++<p> + More precisely, the following (simple, inefficient) definitions hold: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;;; Iterative + (define (string-unfold-right p f g seed base make-final) + (let lp ((seed seed) (ans base)) +@@ -2137,56 +2412,70 @@ cause overflow when constructing large (<em>e.g.</em>, megabyte) strings with + (string (f seed))))) + base)) + </pre> ++<p> + Interested functional programmers may enjoy noting that + <code>string-fold</code> + and <code>string-unfold-right</code> are in some sense inverses. + That is, given operations <var>knull?</var>, <var>kar</var>, <var>kdr</var>, <var>kons</var>, and <var>knil</var> satisfying +-<div class=inset> ++</p> ++<div class="inset"> + <code>(<var>kons</var> (<var>kar</var> <var>x</var>) (<var>kdr</var> <var>x</var>))</code> = <var>x</var> and <code>(<var>knull?</var> <var>knil</var>)</code> = #t + </div> ++<p> + then +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-fold <var>kons</var> <var>knil</var> (string-unfold-right <var>knull?</var> <var>kar</var> <var>kdr</var> <var>x</var>)) = <var>x</var> + </pre> ++<p> + and +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-unfold-right <var>knull?</var> <var>kar</var> <var>kdr</var> (string-fold <var>kons</var> <var>knil</var> <var>s</var>)) = <var>s</var>. + </pre> +- ++<p> + The final string constructed does not share storage with either <var>base</var> + or the value produced by <var>make-final</var>. +- +- <p> ++</p> ++<p> + Note: implementations should take care that runtime stack limits do not + cause overflow when constructing large (<em>e.g.</em>, megabyte) strings with + <code>string-unfold-right.</code> +- ++</p> ++</dd> + + <!-- + ==== string-for-each + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-for-each"></a> +-<code class=proc-def>string-for-each</code><var> proc s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-for-each</code><var> proc s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Apply <var>proc</var> to each character in <var>s</var>. + <code>string-for-each</code> is required to iterate from <var>start</var> to <var>end</var> + in increasing order. +- ++</p> ++</dd> + <!-- + ==== string-for-each-index + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-for-each-index"></a> +-<code class=proc-def>string-for-each-index</code><var> proc s [start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-for-each-index</code><var> proc s [start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Apply <var>proc</var> to each index of <var>s</var>, in order. The optional <var>start/end</var> + pairs restrict the endpoints of the loop. This is simply a + method of looping over a string that is guaranteed to be safe + and correct. +- ++</p> ++<p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let* ((len (string-length s)) + (ans (make-string len))) + (string-for-each-index +@@ -2194,109 +2483,127 @@ Example: + s) + ans) + </pre> +- ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h3><a name="ReplicateRotate">Replicate & rotate</a></h3> ++<h4 id="ReplicateRotate">Replicate & rotate</h4> + + <dl> + + <!-- + ==== xsubstring + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="xsubstring"></a> +-<code class=proc-def>xsubstring</code><var> s from [to start end] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">xsubstring</code><var> s from [to start end] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + This is the "extended substring" procedure that implements replicated + copying of a substring of some string. +- +- <p> ++</p> ++<p> + <var>S</var> is a string; <var>start</var> and <var>end</var> are optional arguments that demarcate + a substring of <var>s</var>, defaulting to 0 and the length of <var>s</var> (<em>i.e.</em>, the whole + string). Replicate this substring up and down index space, in both the + positive and negative directions. For example, if <var>s</var> = "abcdefg", <var>start</var>=3, + and <var>end</var>=6, then we have the conceptual bidirectionally-infinite string +-<div class=inset> ++</p> ++<div class="inset"> + <table> +-<tr align=right> +-<td>... <td>d <td>e <td>f <td>d <td>e <td>f <td>d <td>e <td>f <td>d <td>e <td>f <td>d <td>e <td>f <td>d <td>e <td>f <td>d <td>... +-</tr> +-<tr align=right> +-<td>... <td>-9 <td>-8 <td>-7 <td>-6 <td>-5 <td>-4 <td>-3 <td>-2 <td>-1 <td>0 <td>+1 <td>+2 <td>+3 <td>+4 <td>+5 <td>+6 <td>+7 <td>+8 <td>+9 <td>... +-</tr> ++<tr align="right"> ++<td>... </td><td>d </td><td>e </td><td>f </td><td>d </td><td>e </td><td>f </td><td>d </td><td>e </td><td>f </td><td>d </td><td>e </td><td>f </td><td>d </td><td>e </td><td>f </td><td>d </td><td>e </td><td>f </td><td>d </td><td>... ++</td></tr> ++<tr align="right"> ++<td>... </td><td>-9 </td><td>-8 </td><td>-7 </td><td>-6 </td><td>-5 </td><td>-4 </td><td>-3 </td><td>-2 </td><td>-1 </td><td>0 </td><td>+1 </td><td>+2 </td><td>+3 </td><td>+4 </td><td>+5 </td><td>+6 </td><td>+7 </td><td>+8 </td><td>+9 </td><td>... ++</td></tr> + </table> + </div> +- ++<p> + <code>xsubstring</code> returns the substring of this string beginning at index <var>from</var>, + and ending at <var>to</var> + (which defaults to <var>from</var>+(<var>end</var>-<var>start</var>)). +- +- <p> ++</p> ++<p> + You can use <code>xsubstring</code> to perform a variety of tasks: ++</p> + <ul> + <li> To rotate a string left: <code>(xsubstring "abcdef" 2)</code> => <code>"cdefab"</code> ++ </li> + <li> To rotate a string right: <code>(xsubstring "abcdef" -2)</code> => <code>"efabcd"</code> ++ </li> + <li> To replicate a string: <code>(xsubstring "abc" 0 7)</code> => <code>"abcabca"</code> ++ </li> + </ul> +- +- <p> +- Note that ++<p> ++ Note that ++</p> + <ul> + <li> The <var>from</var>/<var>to</var> indices give a half-open range -- the characters from + index <var>from</var> up to, but not including, index <var>to</var>. ++ </li> + <li> The <var>from</var>/<var>to</var> indices are not in terms of the index space for string <var>s</var>. + They are in terms of the replicated index space of the substring + defined by <var>s</var>, <var>start</var>, and <var>end</var>. ++ </li> + </ul> +- +- <p> ++<p> + It is an error if <var>start</var>=<var>end</var> -- although this is allowed by special + dispensation when <var>from</var>=<var>to</var>. +- ++</p> ++</dd> + <!-- + ==== string-xcopy! + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-xcopy!"></a> +-<code class=proc-def>string-xcopy!</code><var> target tstart s sfrom [sto start end] -> unspecified</var> +-<dd class=proc-def> ++<code class="proc-def">string-xcopy!</code><var> target tstart s sfrom [sto start end] -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Exactly the same as <code>xsubstring,</code> but the extracted text is written + into the string <var>target</var> starting at index <var>tstart</var>. + This operation is not defined if <code>(eq? <var>target</var> <var>s</var>)</code> + or these two arguments + share storage -- you cannot copy a string on top of itself. +- ++</p> ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h3><a name="Miscellaneous">Miscellaneous: insertion, parsing</a></h3> ++<h4 id="Miscellaneous">Miscellaneous: insertion, parsing</h4> + + <dl> + + <!-- + ==== string-replace + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-replace"></a> +-<code class=proc-def>string-replace</code><var> s1 s2 start1 end1 [start2 end2] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-replace</code><var> s1 s2 start1 end1 [start2 end2] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-append (substring/shared <var>s1</var> 0 <var>start1</var>) + (substring/shared <var>s2</var> <var>start2</var> <var>end2</var>) + (substring/shared <var>s1</var> <var>end1</var> (string-length <var>s1</var>))) + </pre> +- ++<p> + That is, the segment of characters in <var>s1</var> from <var>start1</var> to <var>end1</var> + is replaced by the segment of characters in <var>s2</var> from <var>start2</var> to <var>end2</var>. + If <var>start1</var>=<var>end1</var>, this simply splices the <var>s2</var> characters into <var>s1</var> at the + specified index. +- +- <p> ++</p> ++<p> + Examples: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-replace "The TCL programmer endured daily ridicule." + "another miserable perl drone" 4 7 8 22 ) => + "The miserable perl programmer endured daily ridicule." +@@ -2309,74 +2616,82 @@ Example: + (string-insert "It's easy to code it up in Scheme." 5 "really ") => + "It's really easy to code it up in Scheme." + </pre> +- ++</dd> + <!-- + ==== string-tokenize + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-tokenize"></a> +-<code class=proc-def>string-tokenize</code><var> s [token-set start end] -> list</var> +-<dd class=proc-def> ++<code class="proc-def">string-tokenize</code><var> s [token-set start end] -> list</var> ++</dt> ++<dd class="proc-def"> ++<p> + Split the string <var>s</var> into a list of substrings, where each substring is + a maximal non-empty contiguous sequence of characters from the character set + <var>token-set</var>. ++</p> + <ul> + <li> <var>token-set</var> defaults to <code>char-set:graphic</code> + (see <a href="#SRFI-14">SRFI 14</a> + for more on character sets and <code>char-set:graphic</code>). +- <li> If <var>start</var> or <var>end</var> indices are provided, they restrict ++ </li> ++ <li> If <var>start</var> or <var>end</var> indices are provided, they restrict + <code>string-tokenize</code> to operating on the indicated substring of <var>s</var>. ++ </li> + </ul> +- +- <p> ++<p> + This function provides a minimal parsing facility for simple applications. + More sophisticated parsers that handle quoting and backslash effects can + easily be constructed using regular-expression systems; be careful not + to use <code>string-tokenize</code> in contexts where more serious parsing is needed. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (string-tokenize "Help make programs run, run, RUN!") => + ("Help" "make" "programs" "run," "run," "RUN!") + </pre> +- ++</dd> + </dl> + + <!--========================================================================--> +-<h3><a name="FilterDelete">Filtering & deleting</a></h3> ++<h4 id="FilterDelete">Filtering & deleting</h4> + + <dl> + + <!-- + ==== string-filter string-delete + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-filter"></a> + <a name="string-delete"></a> +-<code class=proc-def>string-filter</code><var> char/char-set/pred s [start end] -> string</var> +-<dt class=proc-defn><code class=proc-def>string-delete</code><var> char/char-set/pred s [start end] -> string</var> +-<dd class=proc-def> ++<code class="proc-def">string-filter</code><var> char/char-set/pred s [start end] -> string</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-delete</code><var> char/char-set/pred s [start end] -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + Filter the string <var>s</var>, retaining only those characters that + satisfy / do not satisfy the <var>char/char-set/pred</var> argument. If + this argument is a procedure, it is applied to the character + as a predicate; if it is a char-set, the character is tested + for membership; if it is a character, it is used in an equality test. +- +- <p> ++</p> ++<p> + If the string is unaltered by the filtering operation, these + functions may return either <var>s</var> or a copy of <var>s</var>. +- +- ++</p> ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h2><a name="LowLevelProcs">Low-level procedures</a></h2> ++<h3 id="LowLevelProcs">Low-level procedures</h3> + <p> + The following procedures are useful for writing other string-processing + functions. In a Scheme system that has a module or package system, these + procedures should be contained in a module named "string-lib-internals". +- ++</p> + <!--========================================================================--> +-<h3><a name="ArgUtils">Start/end optional-argument parsing & checking utilities</a></h3> ++<h4 id="ArgUtils">Start/end optional-argument parsing & checking utilities</h4> + + + <dl> +@@ -2384,99 +2699,118 @@ procedures should be contained in a module named "string-lib-internals". + <!-- + ==== string-parse-start+end string-parse-final-start+end + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="string-parse-start+end"></a> + <a name="string-parse-final-start+end"></a> +-<code class=proc-def>string-parse-start+end</code><var> proc s args -> [rest start end]</var> +-<dt class=proc-defn><code class=proc-def>string-parse-final-start+end</code><var> proc s args -> [start end]</var> +-<dd class=proc-def> ++<code class="proc-def">string-parse-start+end</code><var> proc s args -> [rest start end]</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string-parse-final-start+end</code><var> proc s args -> [start end]</var> ++</dt> ++<dd class="proc-def"> ++<p> + <code>string-parse-start+end</code> may be used to parse a pair of optional <var>start/end</var> + arguments from an argument list, defaulting them to 0 and the length of + some string <var>s</var>, respectively. Let the length of string <var>s</var> be <var>slen</var>. +- <ul> ++</p> ++<ul> + <li> If <var>args</var> = (), the function returns + <code>(values '() 0 <var>slen</var>)</code> ++ </li> + <li> If <var>args</var> = (<var>i</var>), <var>i</var> is checked to ensure it is an exact integer, and + that 0 <= i <= <var>slen</var>. + Returns <code>(values (cdr <var>args</var>) <var>i</var> <var>slen</var>)</code>. ++ </li> + <li> If <var>args</var> = <code>(<var>i</var> <var>j</var> ...)</code>, + <var>i</var> and <var>j</var> are checked to ensure they are exact + integers, and that 0 <= <var>i</var> <= <var>j</var> <= + <var>slen</var>. + Returns <code>(values (cddr <var>args</var>) <var>i</var> <var>j</var>)</code>. +- </ul> +- +- <p> ++ </li> ++</ul> ++<p> + If any of the checks fail, an error condition is raised, and <var>proc</var> is used + as part of the error condition -- it should be the client procedure whose + argument list <code>string-parse-start+end</code> is parsing. +- +- <p> ++</p> ++<p> + <code>string-parse-final-start+end</code> is exactly the same, except that the args list + passed to it is required to be of length two or less; if it is longer, + an error condition is raised. It may be used when the optional <var>start/end</var> + parameters are final arguments to the procedure. +- +- <p> ++</p> ++<p> + Note that in all cases, these functions ensure that <var>s</var> is a string + (by necessity, since all cases apply <code>string-length</code> to <var>s</var> either to + default <var>end</var> or to bounds-check it). +- +-<dt class=proc-def> ++</p> ++</dd> ++<dt class="proc-def"> + <a name="let-string-start+end"></a> +-<code class=proc-def>let-string-start+end</code><var> (start end [rest]) proc-exp s-exp args-exp body ... -> value(s)</var> +-<dd class=proc-def> +- ++<code class="proc-def">let-string-start+end</code><var> (start end [rest]) proc-exp s-exp args-exp body ... -> value(s)</var> ++</dt> ++<dd class="proc-def"> ++<p> + [Syntax] ++</p> ++<p> + Syntactic sugar for an application of <code>string-parse-start+end</code> or + <code>string-parse-final-start+end.</code> +- +- <p> ++</p> ++<p> + If a <var>rest</var> variable is given, the form is equivalent to +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (call-with-values + (lambda () (string-parse-start+end <var>proc-exp</var> <var>s-exp</var> <var>args-exp</var>)) + (lambda (<var>rest</var> <var>start</var> <var>end</var>) <var>body</var> ...)) + </pre> +- +- <p> ++<p> + If no <var>rest</var> variable is given, the form is equivalent to +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (call-with-values + (lambda () (string-parse-final-start+end <var>proc-exp</var> <var>s-exp</var> <var>args-exp</var>)) + (lambda (<var>start</var> <var>end</var>) <var>body</var> ...)) + </pre> +- ++</dd> + <!-- + ==== check-substring-spec substring-spec-ok? + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="check-substring-spec"></a> + <a name="substring-spec-ok-p"></a> +-<code class=proc-def>check-substring-spec</code><var> proc s start end -> unspecified</var> +-<dt class=proc-defn><code class=proc-def>substring-spec-ok?</code><var> s start end -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">check-substring-spec</code><var> proc s start end -> unspecified</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">substring-spec-ok?</code><var> s start end -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Check values <var>s</var>, <var>start</var> and <var>end</var> to ensure they specify a valid substring. + This means that <var>s</var> is a string, <var>start</var> and <var>end</var> are exact integers, and + 0 <= <var>start</var> <= <var>end</var> <= + <code>(string-length <var>s</var>)</code> +- +- <p> ++</p> ++<p> + If the values are not proper ++</p> + <ul> + <li> <code>check-substring-spec</code> raises an error condition. <var>proc</var> is used + as part of the error condition, and should be the procedure whose + parameters we are checking. ++ </li> + <li> <code>substring-spec-ok?</code> returns false. ++ </li> + </ul> ++<p> + Otherwise, <code>substring-spec-ok?</code> returns true, and <code>check-substring-spec</code> + simply returns (what it returns is not specified). +- ++</p> ++</dd> + </dl> + + + <!--========================================================================--> +-<h3><a name="KMP">Knuth-Morris-Pratt searching</a></h3> ++<h4 id="KMP">Knuth-Morris-Pratt searching</h4> + <p> + The Knuth-Morris-Pratt string-search algorithm is a method of rapidly scanning + a sequence of text for the occurrence of some fixed string. It has the +@@ -2487,7 +2821,7 @@ the initialisation and searching phases of the algorithm for general use. They + also support searching through sequences of text that arrive in buffered + chunks, in that intermediate search state can be carried across applications + of the search loop from the end of one buffer application to the next. +- ++</p> + <p> + A second critical property of KMP search is that it requires the allocation of + auxiliary memory proportional to the length of the pattern, but <em>constant</em> +@@ -2495,22 +2829,24 @@ in the size of the character type. Alternate searching algorithms frequently + require the construction of a table with an entry for every possible + character -- which can be prohibitively expensive in a 16- or 32-bit character + representation. +- ++</p> + <dl> + <!-- + ==== make-kmp-restart-vector + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="make-kmp-restart-vector"></a> +-<code class=proc-def>make-kmp-restart-vector</code><var> s [c= start end] -> integer-vector</var> +-<dd class=proc-def> ++<code class="proc-def">make-kmp-restart-vector</code><var> s [c= start end] -> integer-vector</var> ++</dt> ++<dd class="proc-def"> ++<p> + Build a Knuth-Morris-Pratt "restart vector," which is useful for quickly + searching character sequences for the occurrence of string <var>s</var> (or the + substring of <var>s</var> demarcated by the optional <var>start/end</var> parameters, if + provided). <var>C=</var> is a character-equality function used to construct the + restart vector. It defaults to <code>char=?</code>; use <code>char-ci=?</code> instead for + case-folded string search. +- ++</p> + <p> + The definition of the restart vector <var>rv</var> for string <var>s</var> is: + If we have matched chars 0..<var>i</var>-1 of <var>s</var> against some search string <var>ss</var>, and +@@ -2519,13 +2855,13 @@ match <var>ss</var>[<var>k</var>]. + If <var>rv</var>[<var>i</var>] = -1, + then punt <var>ss</var>[<var>k</var>] completely, and move on to + <var>ss</var>[<var>k</var>+1] and <var>s</var>[0]. +- ++</p> + <p> + In other words, if you have matched the first <var>i</var> chars of <var>s</var>, but + the <var>i</var>+1'th char doesn't match, + <var>rv</var>[<var>i</var>] tells you what the next-longest + prefix of <var>s</var> is that you have matched. +- ++</p> + <p> + The following string-search function shows how a restart vector is used to + search. Note the attractive feature of the search process: it is "on +@@ -2534,8 +2870,8 @@ data. It simply consumes characters one-at-a-time until declaring a complete + match or reaching the end of the sequence. Thus, it can be easily adapted to + search other character sequences (such as ports) that do not provide random + access to their contents. +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (find-substring pattern source start end) + (let ((plen (string-length pattern)) + (rv (make-kmp-restart-vector pattern))) +@@ -2558,7 +2894,6 @@ access to their contents. + (lp (+ si 1) 0 (- sj 1) plen) ; Punt. + (lp si pi sj (- plen pi)))))))))) + </pre> +- + <p> + The optional <var>start/end</var> parameters restrict the restart vector to the + indicated substring of <var>pat</var>; <var>rv</var> is <var>end</var> - <var>start</var> elements long. If <var>start</var> > 0, +@@ -2568,23 +2903,26 @@ pattern element <var>pat[i + start]</var>. + Elements of <var>rv</var> are themselves indices + that range just over [0, <var>end</var>-<var>start</var>), + <em>not</em> [<var>start</var>, <var>end</var>). +- ++</p> + <p> + Rationale: the actual value of <var>rv</var> is "position independent" -- it + does not depend on where in the <var>pat</var> string the pattern occurs, but + only on the actual characters comprising the pattern. +- ++</p> ++</dd> + <!-- + ==== kmp-step + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="kmp-step"></a> +-<code class=proc-def>kmp-step</code><var> pat rv c i c= p-start -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">kmp-step</code><var> pat rv c i c= p-start -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + This function encapsulates the work performed by one step of the + KMP string search; it can be used to scan strings, input ports, + or other on-line character sources for fixed strings. +- ++</p> + <p> + <var>Pat</var> is the non-empty string specifying the text for which we are searching. + <var>Rv</var> is the Knuth-Morris-Pratt restart vector for the pattern, +@@ -2593,7 +2931,7 @@ The pattern begins at <var>pat</var>[<var>p-start</var>], and is + <code>(string-length <var>rv</var>)</code> characters long. + <var>C=</var> is the character-equality function used to construct the + restart vector, typically <code>char=?</code> or <code>char-ci=?</code>. +- ++</p> + <p> + Suppose the pattern is N characters in length: + <var>pat</var>[<var>p-start</var>, <var>p-start</var> + <var>n</var>). +@@ -2604,19 +2942,20 @@ We have already matched <var>i</var> characters: + returns the new <var>i</var> value -- that is, how much of the pattern we have + matched, <em>including</em> character <var>c</var>. + When <var>i</var> reaches <var>n</var>, the entire pattern has been matched. +- ++</p> + <p> + Thus a typical search loop looks like this: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let lp ((i 0)) + (or (= i n) ; Win -- #t + (and (not (end-of-stream)) ; Lose -- #f + (lp (kmp-step pat rv (get-next-character) i char=? 0))))) + </pre> +- + <p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; Read chars from IPORT until we find string PAT or hit EOF. + (define (port-skip pat iport) + (let* ((rv (make-kmp-restart-vector pat)) +@@ -2628,10 +2967,10 @@ Example: + (lp (kmp-step pat rv c i char=? 0) ; Continue + (+ nchars 1)))))))) + </pre> +- + <p> + This procedure could be defined as follows: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (kmp-step pat rv c i c= p-start) + (let lp ((i i)) + (if (c= c (string-ref pat (+ i p-start))) ; Match => +@@ -2640,27 +2979,29 @@ This procedure could be defined as follows: + (if (= i -1) 0 ; Can't back up more. + (lp i))))))) ; Keep going. + </pre> +- + <p> + Rationale: this procedure takes no optional arguments because it + is intended as an inner-loop primitive and we do not want any + run-time penalty for optional-argument parsing and defaulting, + nor do we wish barriers to procedure integration/inlining. +- ++</p> ++</dd> + <!-- + ==== string-kmp-partial-search + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="string-kmp-partial-search"></a> +-<code class=proc-def>string-kmp-partial-search</code><var> pat rv s i [c= p-start s-start s-end] -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">string-kmp-partial-search</code><var> pat rv s i [c= p-start s-start s-end] -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Applies <code>kmp-step</code> across <var>s</var>; + optional <var>s-start</var>/<var>s-end</var> bounds parameters + restrict search to a substring of <var>s</var>. + The pattern is <code>(vector-length <var>rv</var>)</code> characters long; + optional <var>p-start</var> index indicates non-zero start of pattern + in <var>pat</var>. +- ++</p> + <p> + Suppose <var>plen</var> = <code>(vector-length <var>rv</var>)</code> + is the length of the pattern. +@@ -2668,38 +3009,41 @@ is the length of the pattern. + (that is, 0 <= <var>i</var> < <var>plen</var>) + indicating how much of the pattern has already been matched. + (This means the pattern must be non-empty -- <var>plen</var> > 0.) +- ++</p> + <ul> + <li> On success, returns -<var>j</var>, + where <var>j</var> is the index in <var>s</var> bounding + the <em>end</em> of the pattern -- <em>e.g.</em>, a value that could be used as + the <var>end</var> parameter in a call to <code>substring/shared</code>. +- +-<li> On continue, returns the current search state <var>i'</var> ++</li> ++<li> On continue, returns the current search state <var>i'</var> + (an index into <var>rv</var>) + when the search reached the end of the string. This is a non-negative + integer. ++</li> + </ul> +- ++<p> + Hence: ++</p> + <ul> + <li> A negative return value indicates success, and says + where in the string the match occured. +- ++</li> + <li> A non-negative return value provides the <var>i</var> to use for + continued search in a following string. ++</li> + </ul> +- + <p> + This utility is designed to allow searching for occurrences of a fixed + string that might extend across multiple buffers of text. This is + why, for example, we do not provide the index of the <em>start</em> of the + match on success -- it may have occurred in a previous buffer. +- ++</p> + <p> + To search a character sequence that arrives in "chunks," write a + loop of this form: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let lp ((i 0)) + (and (not (end-of-data?)) ; Lose -- return #f. + (let* ((buf (get-next-chunk)) ; Get or fill up the buffer. +@@ -2707,9 +3051,11 @@ loop of this form: + (if (< i 0) (- i) ; Win -- return end index. + (lp i))))) ; Keep looking. + </pre> ++<p> + Modulo start/end optional-argument parsing, this procedure could + be defined as follows: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (string-kmp-partial-search pat rv s i c= p-start s-start s-end) + (let ((patlen (vector-length rv))) + (let lp ((si s-start) ; An index into S. +@@ -2720,39 +3066,41 @@ be defined as follows: + (kmp-step pat rv (string-ref s si) + vi c= p-start))))))) + </pre> ++</dd> + </dl> + + <!--========================================================================--> +-<h1><a name="ReferenceImp">Reference implementation</a></h1> ++<h2 id="ReferenceImp">Reference implementation</h2> + + <p> + This SRFI comes with a reference implementation. It can be found at: +-<div class=inset> +- <a href="http://srfi.schemers.org/srfi-13/srfi-13.scm">http://srfi.schemers.org/srfi-13/srfi-13.scm</a> ++</p> ++<div class="inset"> ++ <a href="https://srfi.schemers.org/srfi-13/srfi-13.scm">http://srfi.schemers.org/srfi-13/srfi-13.scm</a> + </div> +-<p class=continue> ++<p class="continue"> + I have placed this source on the Net with an unencumbered, "open" copyright. + The prefix/suffix and comparison routines in this code had (extremely distant) + origins in MIT Scheme's string lib, and were substantially reworked by myself. + Being derived from that code, they are covered by the MIT Scheme copyright, + which is a generic BSD-style open-source copyright. See the source file for + details. +- ++</p> + <p> + The KMP string-search code was influenced by implementations written by + Stephen Bevan, Brian Denheyer and Will Fitzgerald. However, this version was + written from scratch by myself. +- ++</p> + <p> + The remainder of the code was written by myself for scsh or for this SRFI; I + have placed this code under the scsh copyright, which is also a generic + BSD-style open-source copyright. +- ++</p> + <p> + The code is written for portability and should be straightforward to port to + any Scheme. The source comments contains detailed notes describing the non-<abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + dependencies. +- ++</p> + <p> + The library is written for clarity and well-commented; the current source is + approximately 1000 lines of source code and 1000 lines of comments and white +@@ -2760,15 +3108,15 @@ space. It is also written for efficiency. Fast paths are provided for common + cases. This is not to say that the implementation can't be tuned up for a + specific Scheme implementation. There are notes in the comments addressing + ways implementors can tune the reference implementation for performance. +- ++</p> + <p> + In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++</p> + + <!--========================================================================--> +-<h1><a name="Acknowledgements">Acknowledgements</a></h1> ++<h2 id="Acknowledgements">Acknowledgements</h2> + + <p> + The design of this library benefited greatly from the feedback provided during +@@ -2782,137 +3130,175 @@ Kiselyov, Bengt Kleberg, Donovan Kolbly, Bruce Korb, Shriram Krishnamurthi, + Bruce Lewis, Tom Lord, Brad Lucier, Dave Mason, David Rush, Klaus Schilling, + Jonathan Sobel, Mike Sperber, Mikael Staldal, Vladimir Tsyshevsky, Donald + Welsh, and Mike Wilson. I am grateful to them for their assistance. +- ++</p> + <p> + I am also grateful the authors, implementors and documentors of all the systems + mentioned in the introduction. Aubrey Jaffer and Kent Pitman should be noted + for their work in producing Web-accessible versions of the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> and Common + Lisp spec, which was a tremendous aid. +- ++</p> + <p> + This is not to imply that these individuals necessarily endorse the final + results, of course. +- ++</p> + <p> + During this document's long development period, great patience was exhibited + by Mike Sperber, who is the editor for the SRFI, and by Hillary Sullivan, + who is not. +- ++</p> + <!--========================================================================--> +-<h1><a name="Links">References & links</a></h1> ++<h2 id="Links">References & links</h2> + + <dl> + +-<dt class=biblio><strong><a name="Case-map">[Case-map]</a></strong> ++<dt class="biblio"><strong><a name="Case-map">[Case-map]</a></strong> ++</dt> + <dd> +- Case mappings. <br> +- Unicode Technical Report 21. <br> ++ <p> ++ Case mappings. <br /> ++ Unicode Technical Report 21. <br /> + <a href="http://www.unicode.org/unicode/reports/tr21/">http://www.unicode.org/unicode/reports/tr21/</a> +- +-<dt class=biblio><strong><a name="CommonLisp">[CommonLisp]</a></strong></dt> +-<dd><em>Common Lisp: the Language.</em><br> +-Guy L. Steele Jr. (editor).<br> +-Digital Press, Maynard, Mass., second edition 1990.<br> ++ </p> ++</dd> ++<dt class="biblio"><strong><a name="CommonLisp">[CommonLisp]</a></strong> ++</dt> ++<dd> ++ <p> ++<em>Common Lisp: the Language.</em><br /> ++Guy L. Steele Jr. (editor).<br /> ++Digital Press, Maynard, Mass., second edition 1990.<br /> + Available at <a href="http://www.elwood.com/alu/table/references.htm#cltl2"> + http://www.elwood.com/alu/table/references.htm#cltl2</a>. ++</p> + <p> +- + The Common Lisp "HyperSpec," produced by Kent Pitman, is essentially + the ANSI spec for Common Lisp: +-<a href="http://www.harlequin.com/education/books/HyperSpec/"> +-http://www.harlequin.com/education/books/HyperSpec/</a>. +- +-<dt class=biblio><strong><a name="Java">[Java]</a></strong> ++<a href="http://www.lispworks.com/documentation/HyperSpec/Front/index.htm"> ++http://www.lispworks.com/documentation/HyperSpec/Front/index.htm</a>. ++</p> ++</dd> ++<dt class="biblio"><strong><a name="Java">[Java]</a></strong> ++</dt> + <dd> +- The following URLs provide documentation on relevant Java classes. <br> ++ <p> ++ The following URLs provide documentation on relevant Java classes. <br /> + + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/StringBuffer.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/StringBuffer.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collator.html">http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collator.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/text/package-summary.html">http://java.sun.com/products/jdk/1.2/docs/api/java/text/package-summary.html</a> +- +-<dt class=biblio><strong><a name="MIT-Scheme">[MIT-Scheme]</a></strong> ++ </p> ++</dd> ++<dt class="biblio"><strong><a name="MIT-Scheme">[MIT-Scheme]</a></strong> ++</dt> + <dd> ++ <p> + <a href="http://www.swiss.ai.mit.edu/projects/scheme/">http://www.swiss.ai.mit.edu/projects/scheme/</a> +- +-<dt class=biblio><strong><a name="R5RS">[R5RS]</a></strong></dt> +-<dd>Revised<sup>5</sup> report on the algorithmic language Scheme.<br> +- R. Kelsey, W. Clinger, J. Rees (editors). <br> +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br> +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br> ++ </p> ++</dd> ++<dt class="biblio"><strong><a name="R5RS">[R5RS]</a></strong> ++</dt> ++<dd> ++ <p> ++ Revised<sup>5</sup> report on the algorithmic language Scheme.<br /> ++ R. Kelsey, W. Clinger, J. Rees (editors). <br /> ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br /> ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br /> + Available at <a href="http://www.schemers.org/Documents/Standards/"> + http://www.schemers.org/Documents/Standards/</a>. +- +-<dt class=biblio><strong>[SRFI]</strong></dt> ++ </p> ++</dd> ++<dt class="biblio"><strong>[SRFI]</strong> ++</dt> + <dd> +- The SRFI web site. <br> +- <a href="http://srfi.schemers.org/">http://srfi.schemers.org/</a> +- +-<dt class=biblio><strong>[SRFI-13]</strong></dt> ++<p> ++ The SRFI web site. <br /> ++ <a href="https://srfi.schemers.org/">http://srfi.schemers.org/</a> ++</p> ++</dd> ++<dt class="biblio"><strong>[SRFI-13]</strong> ++</dt> + <dd> +- SRFI-13: String libraries. <br> +- <a href="http://srfi.schemers.org/srfi-13/">http://srfi.schemers.org/srfi-13/</a> +- ++ <p> ++ SRFI-13: String libraries. <br /> ++ <a href="">http://srfi.schemers.org/srfi-13/</a> ++ </p> + <dl> + <dt> + This document, in HTML: +- <dd><a href="http://srfi.schemers.org/srfi-13/srfi-13.html"> +- http://srfi.schemers.org/srfi-13/srfi-13.html</a> ++ </dt> ++ <dd><a href=""> ++ https://srfi.schemers.org/srfi-13/srfi-13.html</a> + ++ </dd> + <dt> + This document, in plain text format: +- <dd><a href="http://srfi.schemers.org/srfi-13/srfi-13.txt"> +- http://srfi.schemers.org/srfi-13/srfi-13.txt</a> ++ </dt> ++ <dd><a href="https://srfi.schemers.org/srfi-13/srfi-13.txt"> ++ https://srfi.schemers.org/srfi-13/srfi-13.txt</a> + ++ </dd> + <dt> Source code for the reference implementation: ++ </dt> + <dd> +- <a href="http://srfi.schemers.org/srfi-13/srfi-13.scm"> +- http://srfi.schemers.org/srfi-13/srfi-13.scm</a> ++ <a href="https://srfi.schemers.org/srfi-13/srfi-13.scm"> ++ https://srfi.schemers.org/srfi-13/srfi-13.scm</a> + ++ </dd> + <dt> Scheme 48 module specification, with typings: ++ </dt> + <dd> +- <a href="http://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm"> +- http://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm</a> ++ <a href="https://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm"> ++ https://srfi.schemers.org/srfi-13/srfi-13-s48-module.scm</a> ++ </dd> + </dl> + </dd> + +-<dt class=biblio><strong><a name=SRFI-14>[SRFI-14]</a></strong> ++<dt class="biblio"><strong><a name="SRFI-14">[SRFI-14]</a></strong> ++</dt> + <dd> +- SRFI-14: Character-set library. <br> +- <a href="http://srfi.schemers.org/srfi-14/">http://srfi.schemers.org/srfi-14/</a> <br> ++ <p> ++ SRFI-14: Character-set library. <br /> ++ <a href="srfi-14.html">http://srfi.schemers.org/srfi-14/</a> <br /> + The SRFI 14 char-set library defines a character-set data type, + which is used by some procedures in this library. +- +-<dt class=biblio><strong><a name="Unicode">[Unicode]</a></strong> ++ </p> ++</dd> ++<dt class="biblio"><strong><a name="Unicode">[Unicode]</a></strong> ++</dt> + <dd> + <a href="http://www.unicode.org/">http://www.unicode.org/</a> +- +-<dt class=biblio><strong><a name="UnicodeData">[UnicodeData]</a></strong> ++</dd> ++<dt class="biblio"><strong><a name="UnicodeData">[UnicodeData]</a></strong> ++</dt> + <dd> +- The Unicode character database. <br> ++ <p> ++ The Unicode character database. <br /> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> +- <br> ++ <br /> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html</a> +- ++ </p> ++</dd> + </dl> + ++ + <!--========================================================================--> +-<h1><a name="Copyright">Copyright</a></h1> ++<h2 id="Copyright">Copyright</h2> + + <p> + Certain portions of this document -- the specific, marked segments of text + describing the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> procedures -- were adapted with permission from the R5RS + report. +- ++</p> + <p> + All other text is copyright (C) Olin Shivers (1998, 1999, 2000). + All Rights Reserved. +- ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -2935,11 +3321,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> +- ++ <hr /> ++ <address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Michael Sperber</a></address> + </body> +-</html> +- +-<!-- ++</html><!-- + LocalWords: SRFI refs HTML css hackery sans Netscape td pre div init doc + LocalWords: proc def procs defi's defn dl dt defi dd NS RS rs procx dict + LocalWords: stylesheet IE biblio IE's Internationalisation subform maillist +@@ -2970,3 +3355,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + LocalWords: tokenizers iso Pd Ps Pe Pf AB BB BF Sm Sc Sk AF MACRON + LocalWords: PILCROW soh nul ops Shiro Kawai para bignum + --> ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html +index 4167ab3..f42fc23 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-14.html +@@ -1,5 +1,23 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" +- "http://www.w3.org/TR/html4/loose.dtd"> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en-US"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-14 ┃ ++┃ Commit: dcf121392c9650c7bd678b595c8e3ffc6875db47 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <!-- + - Do a paragraph check <p> + - The Unicode char tables are messed up, but it can't be fixed w/o CSS2 +@@ -9,18 +27,17 @@ + You can't put sharp in a path, so anything goes, really. + Nonetheless, some of these confuse Netscape, so I'll avoid them. + --> +- + <!--========================================================================--> +-<html lang=en-US> +- <head> +- <meta name="keywords" content="Scheme, programming language, list processing, SRFI, youthful devotees of intra-gender communion"> +- <link rev=made href="mailto:shivers@ai.mit.edu"> ++ <meta content="Scheme, programming language, list processing, SRFI" name="keywords" /> + <title>SRFI 14: Character-set Library</title> +- ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + <!-- Should have a media=all to get, for example, printing to work. + == But my Netscape will completely ignore the tag if I do that. + --> + <style type="text/css"> ++ /*<![CDATA[*/ + /* A little general layout hackery for headers & the title. */ + body { margin-left: +7%; + font-family: "Helvetica", sans-serif; +@@ -32,8 +49,8 @@ + + div.inset { margin-left: +5%; } + +- h1 { margin-left: -5%; } +- h1, h2 { clear: both; } ++ h2 { margin-left: -5%; } ++ h2, h3 { clear: both; } + h1, h2, h3, h4, h5, h6 { color: blue } + div.title-text { font-size: large; font-weight: bold; } + h3 { margin-top: 2em; margin-bottom: 0em } +@@ -110,10 +127,10 @@ + ** development process and kill them when the document's done. + */ + a.draft { color: red; } +- ++ /*]]>*/ + </style> +- +- <style type="text/css" media=all> ++ <style media="all" type="text/css"> ++ /*<![CDATA[*/ + /* Nastiness: Here, I'm using a bug to work around a bug. + ** Netscape rendering bugs mean you need bogus <dt> and <dd> + ** margin settings -- settings which screw up IE's proper rendering. +@@ -140,75 +157,105 @@ + /* Spread out bibliographic lists. */ + dt.biblio { margin-top: 3ex; margin-bottom: 0ex; } + dd.biblio { margin-bottom: 1ex; } ++ /*]]>*/ + </style> + </head> +- + <body> +- + <!--========================================================================--> +-<H1>Title</H1> ++<h1>SRFI 14: Character-set Library</h1> + +-<div class=title-text>SRFI 14: Character-set Library</div> ++<p>by Olin Shivers</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 14 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-14/srfi-14.html">https://srfi.schemers.org/srfi-14/srfi-14.html</a>.</p></blockquote></blockquote></blockquote> + +-<!--========================================================================--> +-<H1>Author</H1> +- +-Olin Shivers +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-14/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/10/17 +-<LI>Draft: 1999/10/30-1999/12/30 +-<LI>Revised: 2000/04/30 +-<LI>Revised: 2000/04/30 +-<LI>Revised: 2000/06/09 +-<LI>Revised: 2000/12/23 +-</UL> ++<h2 id="status">Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+14+at+srfi+dotschemers+dot+org">srfi-14@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-14">archive</a>.</p> ++<ul> ++ <li>Received: 1999-10-17</li> ++ <li>Draft: 1999-10-30--1999-12-30</li> ++ <li>Revised: 2000-04-30</li> ++ <li>Revised: 2000-04-30</li> ++ <li>Revised: 2000-06-09</li> ++ <li>Revised: 2000-12-23</li> ++ <li>Post-finalization notes: ++ <ul> ++ <li> ++ 2019-12-09 (In a ++ <a href="https://srfi.schemers.org/srfi-14/contrib/unicode-2019/CharsetDefs.html">separate document</a>, ++ added notes by John Cowan on relevant changes to Unicode ++ since publication of this SRFI. The author of SRFI 14, Olin Shivers, ++ has not yet expressed an opinion on the notes.) ++ </li> ++ </ul> ++ </li> ++</ul> ++<!-- Commented out till Olin approves ++<a name="PostFinalizationNote1"></a> ++<p><b>Post-finalization note 1 (2019):</b> ++The tables in the ++<a href="#StandardCharsetDefs"> ++Unicode, Latin-1 and ASCII definitions of the standard character sets</a> ++section below reflect Java 1.0, which in turn reflects Unicode 2.0. ++Unicode's definitions of these groups of characters has been ++substantially revised and updated since then, although the ASCII and Latin-1 ++definitions are frozen and will always be correct.</p> ++ ++<p>This note recommends that implementers of new implementations and ++maintainers of existing ones update their implementations to use ++the current Unicode definitions, as detailed in ++<a href="contrib/unicode-2019/CharsetDefs.html"> ++the supplementary CharsetDefinitions file</a>. ++Software to assist in this task may be present in the ++<a href="contrib/unicode-2019"> ++contrib/unicode-2019</a> directory of the repository. ++</p> ++--> + + <!--========================================================================--> +-<h1>Table of contents</H1> ++<h2>Table of contents</h2> + + <!-- A bug in netscape (?) keeps the first link in this UL from being active. + ==== So the Abstract link be dead. 99/8/22 -Olin + --> +-<ul id=toc-table> +-<li><a href="#Abstract">Abstract</a> +-<li><a href="#VariableIndex">Variable index</a> +-<li><a href="#Rationale">Rationale</a> +- <ul> +- <li><a href="#LinearUpdateOperations">"Linear-update" operations</a> +- <li><a href="#ExtraSRFI">Extra-SRFI recommendations</a> +- </ul> +- +-<li><a href="#Specification">Specification</a> +- <ul> +- <li><a href="#GeneralProcs">General procedures</a> +- <li><a href="#Iterating">Iterating over character sets</a> +- <li><a href="#Creating">Creating character sets</a> +- <li><a href="#Querying">Querying character sets</a> +- <li><a href="#Algebra">Character set algebra</a> +- <li><a href="#StandardCharsets">Standard character sets</a> +- </ul> +- +-<li><a href="#StandardCharsetDefs">Unicode, Latin-1 and ASCII definitions of the standard character sets</a> +-<li><a href="#ReferenceImp">Reference implementation</a> +-<li><a href="#Acknowledgements">Acknowledgements</a> +-<li><a href="#Links">References & Links</a> +-<li><a href="#Copyright">Copyright</a> ++<ul id="toc-table"> ++ <li><a href="#Abstract">Abstract</a></li> ++ <li><a href="#VariableIndex">Variable index</a></li> ++ <li><a href="#Rationale">Rationale</a> ++ <ul> ++ <li><a href="#LinearUpdateOperations">"Linear-update" operations</a></li> ++ <li><a href="#ExtraSRFI">Extra-SRFI recommendations</a></li> ++ </ul> ++ </li> ++ <li><a href="#Specification">Specification</a> ++ <ul> ++ <li><a href="#GeneralProcs">General procedures</a></li> ++ <li><a href="#Iterating">Iterating over character sets</a></li> ++ <li><a href="#Creating">Creating character sets</a></li> ++ <li><a href="#Querying">Querying character sets</a></li> ++ <li><a href="#Algebra">Character set algebra</a></li> ++ <li><a href="#StandardCharsets">Standard character sets</a></li> ++ </ul> ++ </li> ++ <li><a href="#StandardCharsetDefs">Unicode, Latin-1 and ASCII definitions of the standard character sets</a></li> ++ <li><a href="#ReferenceImp">Reference implementation</a></li> ++ <li><a href="#Acknowledgements">Acknowledgements</a></li> ++ <li><a href="#Links">References & Links</a></li> ++ <li><a href="#Copyright">Copyright</a></li> + </ul> + + <!--========================================================================--> +-<h1><a name="Abstract">Abstract</a></H1> ++<h2 id="Abstract">Abstract</h2> + <p> +- + The ability to efficiently represent and manipulate sets of characters is an + unglamorous but very useful capability for text-processing code -- one that + tends to pop up in the definitions of other libraries. Hence it is useful to + specify a general substrate for this functionality early. This SRFI defines a + general library that provides this functionality. +- ++</p> ++<p> + It is accompanied by a reference implementation for the spec. The reference + implementation is fairly efficient, straightforwardly portable, and has a + "free software" copyright. The implementation is tuned for "small" 7 or 8 +@@ -216,90 +263,97 @@ bit character types, such as ASCII or Latin-1; the data structures and + algorithms would have to be altered for larger 16 or 32 bit character types + such as Unicode -- however, the specs have been carefully designed with these + larger character types in mind. +- ++</p> ++<p> + Several forthcoming SRFIs can be defined in terms of this one: ++</p> + <ul> +- <li> string library +- <li> delimited input procedures (<em>e.g.</em>, <code>read-line</code>) +- <li> regular expressions ++ <li>string library</li> ++ <li>delimited input procedures (<em>e.g.</em>, <code>read-line</code>)</li> ++ <li> regular expressions</li> + </ul> + +- + <!--========================================================================--> +-<h1><a name="VariableIndex">Variable Index</a></h1> ++<h2 id="VariableIndex">Variable Index</h2> + <p> + Here is the complete set of bindings -- procedural and otherwise -- + exported by this library. In a Scheme system that has a module or package + system, these procedures should be contained in a module named "char-set-lib". +- +-<div class=indent> ++</p> ++<div class="indent"> + <dl> +-<dt class=proc-index> Predicates & comparison +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#char-set-p">char-set?</a> <a href="#char-set=">char-set=</a> <a href="#char-set<=">char-set<=</a> <a href="#char-set-hash">char-set-hash</a> ++<dt class="proc-index"> Predicates & comparison ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#char-set-p">char-set?</a> <a href="#char-set%3D">char-set=</a> <a href="#char-set%3C%3D">char-set<=</a> <a href="#char-set-hash">char-set-hash</a> + </pre> +- +-<dt class=proc-index> Iterating over character sets +-<dd class=proc-index> +-<pre class=proc-index> ++</dd> ++<dt class="proc-index"> Iterating over character sets ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> + <a href="#char-set-cursor">char-set-cursor</a> <a href="#char-set-ref">char-set-ref</a> <a href="#char-set-cursor-next">char-set-cursor-next</a> <a href="#end-of-char-set-p">end-of-char-set?</a> + <a href="#char-set-fold">char-set-fold</a> <a href="#char-set-unfold">char-set-unfold</a> <a href="#char-set-unfold!">char-set-unfold!</a> + <a href="#char-set-for-each">char-set-for-each</a> <a href="#char-set-map">char-set-map</a> + </pre> +- +-<dt class=proc-index> Creating character sets +-<dd class=proc-index> +-<pre class=proc-index> ++</dd> ++<dt class="proc-index"> Creating character sets ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> + <a href="#char-set-copy">char-set-copy</a> <a href="#char-set">char-set</a> + +-<a href="#list->char-set">list->char-set</a> <a href="#string->char-set">string->char-set</a> +-<a href="#list->char-set!">list->char-set!</a> <a href="#string->char-set!">string->char-set!</a> ++<a href="#list-%3Echar-set">list->char-set</a> <a href="#string-%3Echar-set">string->char-set</a> ++<a href="#list-%3Echar-set!">list->char-set!</a> <a href="#string-%3Echar-set!">string->char-set!</a> + +-<a href="#char-set-filter">char-set-filter</a> <a href="#ucs-range->char-set">ucs-range->char-set</a> <a href="# +-char-set-filter!"> +-char-set-filter!</a> <a href="#ucs-range->char-set!">ucs-range->char-set!</a> ++<a href="#char-set-filter">char-set-filter</a> <a href="#ucs-range-%3Echar-set">ucs-range->char-set</a> <a href="#char-set-filter!"> ++char-set-filter!</a> <a href="#ucs-range-%3Echar-set!">ucs-range->char-set!</a> + +-<a href="#->char-set">->char-set</a> ++<a href="#-%3Echar-set">->char-set</a> + </pre> +- +-<dt class=proc-index> Querying character sets +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#char-set->list">char-set->list</a> <a href="#char-set->string">char-set->string</a> ++</dd> ++<dt class="proc-index"> Querying character sets ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#char-set-%3Elist">char-set->list</a> <a href="#char-set-%3Estring">char-set->string</a> + <a href="#char-set-size">char-set-size</a> <a href="#char-set-count">char-set-count</a> <a href="#char-set-contains-p">char-set-contains?</a> + <a href="#char-set-every">char-set-every</a> <a href="#char-set-any">char-set-any</a> + </pre> +- +-<dt class=proc-index> Character-set algebra +-<dd class=proc-index> +-<pre class=proc-index> ++</dd> ++<dt class="proc-index"> Character-set algebra ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> + <a href="#char-set-adjoin">char-set-adjoin</a> <a href="#char-set-delete">char-set-delete</a> + <a href="#char-set-adjoin!">char-set-adjoin!</a> <a href="#char-set-delete!">char-set-delete!</a> + + <a href="#char-set-complement">char-set-complement</a> <a href="#char-set-union">char-set-union</a> <a href="#char-set-intersection">char-set-intersection</a> + <a href="#char-set-complement!">char-set-complement!</a> <a href="#char-set-union!">char-set-union!</a> <a href="#char-set-intersection!">char-set-intersection!</a> + +-<a href="#char-set-difference">char-set-difference</a> <a href="#char-set-xor">char-set-xor</a> <a href="#char-set-diff+intersection">char-set-diff+intersection</a> +-<a href="#char-set-difference!">char-set-difference!</a> <a href="#char-set-xor!">char-set-xor!</a> <a href="#char-set-diff+intersection!">char-set-diff+intersection!</a> ++<a href="#char-set-difference">char-set-difference</a> <a href="#char-set-xor">char-set-xor</a> <a href="#char-set-diff%2Bintersection">char-set-diff+intersection</a> ++<a href="#char-set-difference!">char-set-difference!</a> <a href="#char-set-xor!">char-set-xor!</a> <a href="#char-set-diff%2Bintersection!">char-set-diff+intersection!</a> + </pre> +- +-<dt class=proc-index> Standard character sets +-<dd class=proc-index> +-<pre class=proc-index> +-<a href="#char-set:lower-case">char-set:lower-case</a> <a href="#char-set:upper-case">char-set:upper-case</a> <a href="#char-set:title-case">char-set:title-case</a> +-<a href="#char-set:letter">char-set:letter</a> <a href="#char-set:digit">char-set:digit</a> <a href="#char-set:letter+digit">char-set:letter+digit</a> +-<a href="#char-set:graphic">char-set:graphic</a> <a href="#char-set:printing">char-set:printing</a> <a href="#char-set:whitespace">char-set:whitespace</a> +-<a href="#char-set:iso-control">char-set:iso-control</a> <a href="#char-set:punctuation">char-set:punctuation</a> <a href="#char-set:symbol">char-set:symbol</a> +-<a href="#char-set:hex-digit">char-set:hex-digit</a> <a href="#char-set:blank">char-set:blank</a> <a href="#char-set:ascii">char-set:ascii</a> +-<a href="#char-set:empty">char-set:empty</a> <a href="#char-set:full">char-set:full</a> ++</dd> ++<dt class="proc-index"> Standard character sets ++</dt> ++<dd class="proc-index"> ++<pre class="proc-index"> ++<a href="#char-set%3Alower-case">char-set:lower-case</a> <a href="#char-set%3Aupper-case">char-set:upper-case</a> <a href="#char-set%3Atitle-case">char-set:title-case</a> ++<a href="#char-set%3Aletter">char-set:letter</a> <a href="#char-set%3Adigit">char-set:digit</a> <a href="#char-set%3Aletter%2Bdigit">char-set:letter+digit</a> ++<a href="#char-set%3Agraphic">char-set:graphic</a> <a href="#char-set%3Aprinting">char-set:printing</a> <a href="#char-set%3Awhitespace">char-set:whitespace</a> ++<a href="#char-set%3Aiso-control">char-set:iso-control</a> <a href="#char-set%3Apunctuation">char-set:punctuation</a> <a href="#char-set%3Asymbol">char-set:symbol</a> ++<a href="#char-set%3Ahex-digit">char-set:hex-digit</a> <a href="#char-set%3Ablank">char-set:blank</a> <a href="#char-set%3Aascii">char-set:ascii</a> ++<a href="#char-set%3Aempty">char-set:empty</a> <a href="#char-set%3Afull">char-set:full</a> + </pre> + ++</dd> + </dl> + </div> + + <!--========================================================================--> +-<h1><a name="Rationale">Rationale</a></h1> ++<h2 id="Rationale">Rationale</h2> + + <p> + The ability to efficiently manipulate sets of characters is quite +@@ -307,16 +361,16 @@ useful for text-processing code. Encapsulating this functionality in + a general, efficiently implemented library can assist all such code. + This library defines a new data structure to represent these sets, called + a "char-set." The char-set type is distinct from all other types. +- ++</p> + <p> + This library is designed to be portable across implementations that use + different character types and representations, especially ASCII, Latin-1 + and Unicode. Some effort has been made to preserve compatibility with Java + in the Unicode case (see the definition of <code>char-set:whitespace</code> for the + single real deviation). +- ++</p> + <!--========================================================================--> +-<h2><a name="LinearUpdateOperations">Linear-update operations</a></h2> ++<h2 id="LinearUpdateOperations">Linear-update operations</h2> + + <p> + The procedures of this SRFI, by default, are "pure functional" -- they do not +@@ -327,39 +381,43 @@ to construct their result. An implementation may legally implement these + procedures as pure, side-effect-free functions, or it may implement them using + side effects, depending upon the details of what is the most efficient or + simple to implement in terms of the underlying representation. +- ++</p> + <p> + The linear-update routines all have names ending with "!". +- ++</p> + <p> + Clients of these procedures <em>may not</em> rely upon these procedures working by + side effect. For example, this is not guaranteed to work: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let* ((cs1 (char-set #\a #\b #\c)) ; cs1 = {a,b,c}. + (cs2 (char-set-adjoin! cs1 #\d))) ; Add d to {a,b,c}. + cs1) ; Could be either {a,b,c} or {a,b,c,d}. + </pre> +-<p class=continue> ++<p class="continue"> + However, this is well-defined: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (let ((cs (char-set #\a #\b #\c))) + (char-set-adjoin! cs #\d)) ; Add d to {a,b,c}. + </pre> +- + <p> + So clients of these procedures write in a functional style, but must + additionally be sure that, when the procedure is called, there are no other + live pointers to the potentially-modified character set (hence the term + "linear update"). +- ++</p> + <p> + There are two benefits to this convention: ++</p> + <ul> + <li> Implementations are free to provide the most efficient possible + implementation, either functional or side-effecting. ++ </li> + <li> Programmers may nonetheless continue to assume that character sets + are purely functional data structures: they may be reliably shared + without needing to be copied, uniquified, and so forth. ++ </li> + </ul> + + <p> +@@ -369,136 +427,151 @@ be represented in an ASCII Scheme with 4 32-bit words. Pure set-algebra + operations on such a representation are very fast and efficient. Programmers + who code using linear-update operations are guaranteed the system will + provide the best implementation across multiple platforms. +- ++</p> + <p> + In practice, these procedures are most useful for efficiently constructing + character sets in a side-effecting manner, in some limited local context, + before passing the character set outside the local construction scope to be + used in a functional manner. +- ++</p> + <p> + Scheme provides no assistance in checking the linearity of the potentially + side-effected parameters passed to these functions --- there's no linear + type checker or run-time mechanism for detecting violations. (But + sophisticated programming environments, such as DrScheme, might help.) +- ++</p> + <!--========================================================================--> +-<h2><a name="ExtraSRFI">Extra-SRFI recommendations</a></h2> ++<h2 id="ExtraSRFI">Extra-SRFI recommendations</h2> + <p> + Users are cautioned that the R5RS predicates +-<div class=inset><code> +-char-alphabetic? <br> +-char-numeric? <br> +-char-whitespace? <br> +-char-upper-case? <br> +-char-lower-case? <br> ++</p> ++<div class="inset"><code> ++char-alphabetic? <br /> ++char-numeric? <br /> ++char-whitespace? <br /> ++char-upper-case? <br /> ++char-lower-case? <br /> + </code> + </div> +-<p class=continue> ++<p class="continue"> + may or may not be in agreement with the SRFI 14 base character sets +-<div class=inset> ++</p> ++<div class="inset"> + <code> +-char-set:letter<br> +-char-set:digit<br> +-char-set:whitespace<br> +-char-set:upper-case<br> +-char-set:lower-case<br> ++char-set:letter<br /> ++char-set:digit<br /> ++char-set:whitespace<br /> ++char-set:upper-case<br /> ++char-set:lower-case<br /> + </code> + </div> +-<p class=continue> ++<p class="continue"> + Implementors are strongly encouraged to bring these predicates into + agreement with the base character sets of this SRFI; not to do so risks + major confusion. +- ++</p> + + <!--========================================================================--> +-<h1><a name="Specification">Specification</a></h1> ++<h2 id="Specification">Specification</h2> + <p> + In the following procedure specifications: ++</p> + <ul> + <li> A <var>cs</var> parameter is a character set. +- ++ </li> + <li> An <var>s</var> parameter is a string. +- ++ </li> + <li> A <var>char</var> parameter is a character. +- ++ </li> + <li> A <var>char-list</var> parameter is a list of characters. +- +- <li> A <var>pred</var> parameter is a unary character predicate procedure, returning ++ </li> ++ <li> A <var>pred</var> parameter is a unary character predicate procedure, returning + a true/false value when applied to a character. +- ++ </li> + <li> An <var>obj</var> parameter may be any value at all. ++ </li> + </ul> + + <p> + Passing values to procedures with these parameters that do not satisfy these + types is an error. +- ++</p> + <p> + Unless otherwise noted in the specification of a procedure, procedures + always return character sets that are distinct (from the point of view + of the linear-update operations) from the parameter character sets. For + example, <code>char-set-adjoin</code> is guaranteed to provide a fresh character set, + even if it is not given any character parameters. +- ++</p> + <p> + Parameters given in square brackets are optional. Unless otherwise noted in the + text describing the procedure, any prefix of these optional parameters may + be supplied, from zero arguments to the full list. When a procedure returns + multiple values, this is shown by listing the return values in square + brackets, as well. So, for example, the procedure with signature +-<pre class=code-example> +-halts? <var>f [x init-store]</var> -> <var>[boolean integer]</var> ++</p> ++<pre class="code-example"> ++halts? <var>f [x init-store]</var> -> <var>[boolean integer]</var> + </pre> ++<p class="continue"> + would take one (<var>f</var>), two (<var>f</var>, <var>x</var>) + or three (<var>f</var>, <var>x</var>, <var>init-store</var>) input parameters, + and return two values, a boolean and an integer. +- ++</p> + <p> + A parameter followed by "<code>...</code>" means zero-or-more elements. + So the procedure with the signature +-<pre class=code-example> +-sum-squares <var>x ... </var> -> <var>number</var> ++</p> ++<pre class="code-example"> ++sum-squares <var>x ... </var> -> <var>number</var> + </pre> ++<p class="continue"> + takes zero or more arguments (<var>x ...</var>), + while the procedure with signature +-<pre class=code-example> +-spell-check <var>doc dict<sub>1</sub> dict<sub>2</sub> ...</var> -> <var>string-list</var> ++</p> ++<pre class="code-example"> ++spell-check <var>doc dict<sub>1</sub> dict<sub>2</sub> ...</var> -> <var>string-list</var> + </pre> ++<p class="continue"> + takes two required parameters + (<var>doc</var> and <var>dict<sub>1</sub></var>) + and zero or more optional parameters (<var>dict<sub>2</sub> ...</var>). +- ++</p> + + <!--========================================================================--> +-<h2><a name="GeneralProcs">General procedures</a></h2> ++<h2 id="GeneralProcs">General procedures</h2> + <dl> + + <!-- + ==== char-set? + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-p"></a> +-<code class=proc-def>char-set?</code><var> obj -> boolean</var> +-<dd class=proc-def> +- ++<code class="proc-def">char-set?</code><var> obj -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Is the object <var>obj</var> a character set? +- ++</p> ++</dd> + <!-- + ==== char-set= + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set="></a> +-<code class=proc-def>char-set=</code><var> cs<sub>1</sub> ... -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">char-set=</code><var> cs<sub>1</sub> ... -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Are the character sets equal? ++</p> + <p> + Boundary cases: +-<pre class=code-example> +-(char-set=) => <var>true</var> +-(char-set= cs) => <var>true</var> ++</p> ++<pre class="code-example"> ++(char-set=) => <var>true</var> ++(char-set= cs) => <var>true</var> + </pre> +- + <p> + Rationale: transitive binary relations are generally extended to n-ary + relations in Scheme, which enables clearer, more concise code to be +@@ -506,15 +579,17 @@ and zero or more optional parameters (<var>dict<sub>2</sub> ...</var>). + certainly not arise in first-order uses of such relations, they may well + arise in higher-order cases or macro-generated code. + <em>E.g.,</em> consider +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (apply char-set= cset-list) + </pre> +-<p class=continue> ++<p class="continue"> + This is well-defined if the list is empty or a singleton list. Hence + we extend these relations to any number of arguments. Implementors + have reported actual uses of n-ary relations in higher-order cases + allowing for fewer than two arguments. The way of Scheme is to handle the + general case; we provide the fully general extension. ++</p> + <p> + A counter-argument to this extension is that + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>'s +@@ -523,63 +598,69 @@ and zero or more optional parameters (<var>dict<sub>2</sub> ...</var>). + require at least two arguments, hence + this decision is a break with the prior convention -- although it is + at least one that is backwards-compatible. +- ++</p> ++</dd> + <!-- + ==== char-set<= + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set<="></a> +-<code class=proc-def>char-set<=</code><var> cs<sub>1</sub> ... -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def"> ++<a name="char-set<="></a> ++<code class="proc-def">char-set<=</code><var> cs<sub>1</sub> ... -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns true if every character set <var>cs<sub>i</sub></var> is + a subset of character set <var>cs<sub>i+1</sub></var>. +- ++</p> + <p> + Boundary cases: +-<pre class=code-example> +-(char-set<=) => <var>true</var> +-(char-set<= cs) => <var>true</var> ++</p> ++<pre class="code-example"> ++(char-set<=) => <var>true</var> ++(char-set<= cs) => <var>true</var> + </pre> + <p> + Rationale: See <code>char-set=</code> for discussion of zero- and one-argument + applications. Consider testing a list of char-sets for monotonicity +-with +-<pre class=code-example> +-(apply char-set<= cset-list) ++with ++</p> ++<pre class="code-example"> ++(apply char-set<= cset-list) + </pre> +- ++</dd> + <!-- + ==== char-set-hash + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-hash"></a> +-<code class=proc-def>char-set-hash</code><var> cs [bound] -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-hash</code><var> cs [bound] -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Compute a hash value for the character set <var>cs</var>. + <var>Bound</var> is a non-negative + exact integer specifying the range of the hash function. A positive + value restricts the return value to the range [0,<var>bound</var>). +- +- <p> ++</p> ++<p> + If <var>bound</var> is either zero or not given, the implementation may use + an implementation-specific default value, chosen to be as large as + is efficiently practical. For instance, the default range might be chosen + for a given implementation to map all strings into the range of + integers that can be represented with a single machine word. +- +- +- <p> ++</p> ++<p> + Invariant: +-<pre class=code-example> +-(char-set= cs<sub>1</sub> cs<sub>2</sub>) => (= (char-set-hash cs<sub>1</sub> b) (char-set-hash cs<sub>2</sub> b)) ++</p> ++<pre class="code-example"> ++(char-set= cs<sub>1</sub> cs<sub>2</sub>) => (= (char-set-hash cs<sub>1</sub> b) (char-set-hash cs<sub>2</sub> b)) + </pre> +- +- <p> ++<p> + A legal but nonetheless discouraged implementation: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (char-set-hash cs . maybe-bound) 1) + </pre> +- + <p> + Rationale: allowing the user to specify an explicit bound simplifies user + code by removing the mod operation that typically accompanies every hash +@@ -590,29 +671,31 @@ with + intermediate values never overflow into bignum integers, allowing the + implementor to provide a fixnum-specific "fast path" for computing the + common cases very rapidly. +- ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="Iterating">Iterating over character sets</a></h2> ++<h2 id="Iterating">Iterating over character sets</h2> + + <dl> + <!-- + ==== char-set-cursor char-set-ref char-set-cursor-next end-of-char-set? + ============================================================================--> +-<dt class=proc-def1> +-<a name="char-set-cursor"></a> +-<a name="char-set-ref"></a> +-<a name="char-set-cursor-next"></a> +-<a name="end-of-char-set-p"></a> +-<code class=proc-def>char-set-cursor</code><var> cset -> cursor</var> +-<dt class=proc-defi> +-<code class=proc-def>char-set-ref</code><var> cset cursor -> char</var> +-<dt class=proc-defi> +-<code class=proc-def>char-set-cursor-next</code><var> cset cursor -> cursor</var> +-<dt class=proc-defn> +-<code class=proc-def>end-of-char-set?</code><var> cursor -> boolean</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="char-set-cursor"> ++<code class="proc-def">char-set-cursor</code><var> cset -> cursor</var> ++</dt> ++<dt class="proc-defi" id="char-set-ref"> ++<code class="proc-def">char-set-ref</code><var> cset cursor -> char</var> ++</dt> ++<dt class="proc-defi" id="char-set-cursor-next"> ++<code class="proc-def">char-set-cursor-next</code><var> cset cursor -> cursor</var> ++</dt> ++<dt class="proc-defn" id="end-of-char-set-p"> ++<code class="proc-def">end-of-char-set?</code><var> cursor -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + Cursors are a low-level facility for iterating over the characters in a + set. A cursor is a value that indexes a character in a char set. + <code>char-set-cursor</code> produces a new cursor for a given char set. +@@ -624,28 +707,29 @@ with + answers true to <code>end-of-char-set?</code>. + It is an error to pass such a cursor to <code>char-set-ref</code> or to + <code>char-set-cursor-next</code>. +- ++</p> + <p> + A cursor value may not be used in conjunction with a different character + set; if it is passed to <code>char-set-ref</code> or + <code>char-set-cursor-next</code> with + a character set other than the one used to create it, the results and + effects are undefined. +- ++</p> + <p> + Cursor values are <em>not</em> necessarily distinct from other types. + They may be + integers, linked lists, records, procedures or other values. This license + is granted to allow cursors to be very "lightweight" values suitable for + tight iteration, even in fairly simple implementations. +- ++</p> + <p> + Note that these primitives are necessary to export an iteration facility + for char sets to loop macros. +- ++</p> + <p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define cs (char-set #\G #\a #\T #\e #\c #\h)) + + ;; Collect elts of CS into a list. +@@ -653,16 +737,15 @@ with + (if (end-of-char-set? cur) ans + (lp (char-set-cursor-next cs cur) + (cons (char-set-ref cs cur) ans)))) +- => (#\G #\T #\a #\c #\e #\h) ++ => (#\G #\T #\a #\c #\e #\h) + + ;; Equivalently, using a list unfold (from SRFI 1): + (unfold-right end-of-char-set? + (curry char-set-ref cs) + (curry char-set-cursor-next cs) + (char-set-cursor cs)) +- => (#\G #\T #\a #\c #\e #\h) ++ => (#\G #\T #\a #\c #\e #\h) + </pre> +- + <p> + Rationale: Note that the cursor API's four functions "fit" the functional + protocol used by the unfolders provided by the list, string and char-set +@@ -674,26 +757,31 @@ with + character set, then this function returned false instead of the character + value, and another end-of-char-set cursor. In this way, the other three + functions of the current API were combined together. +- ++</p> ++</dd> + <!-- + ==== char-set-fold + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-fold"></a> +-<code class=proc-def>char-set-fold</code><var> kons knil cs -> object</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-fold</code><var> kons knil cs -> object</var> ++</dt> ++<dd class="proc-def"> ++<p> + This is the fundamental iterator for character sets. Applies the function + <var>kons</var> across the character set <var>cs</var> using initial state value <var>knil</var>. That is, + if <var>cs</var> is the empty set, the procedure returns <var>knil</var>. Otherwise, some + element <var>c</var> of <var>cs</var> is chosen; + let <var>cs'</var> be the remaining, unchosen characters. + The procedure returns +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-set-fold <var>kons</var> (<var>kons</var> <var>c</var> <var>knil</var>) <var>cs'</var>) + </pre> +- <p> ++<p> + Examples: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + ;; CHAR-SET-MEMBERS + (lambda (cs) (char-set-fold cons '() cs)) + +@@ -705,34 +793,39 @@ with + (char-set-fold (lambda (c i) (if (vowel? c) (+ i 1) i)) + 0 cs)) + </pre> ++</dd> + + <!-- + ==== char-set-unfold char-set-unfold! + ============================================================================--> +-<dt class=proc-def1> +-<a name="char-set-unfold"></a> +-<a name="char-set-unfold!"></a> +-<code class=proc-def>char-set-unfold </code><var> f p g seed [base-cs] -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-unfold!</code><var> f p g seed base-cs -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="char-set-unfold"> ++<code class="proc-def">char-set-unfold </code><var> f p g seed [base-cs] -> char-set</var> ++</dt> ++<dt class="proc-defn" id="char-set-unfold!"><code class="proc-def">char-set-unfold!</code><var> f p g seed base-cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + This is a fundamental constructor for char-sets. ++</p> + <ul> + <li> <var>G</var> is used to generate a series of "seed" values from the initial seed: + <var>seed</var>, (<var>g</var> <var>seed</var>), (<var>g<sup>2</sup></var> <var>seed</var>), (<var>g<sup>3</sup></var> <var>seed</var>), ... +- <li> <var>P</var> tells us when to stop -- when it returns true when applied to one ++ </li> ++ <li> <var>P</var> tells us when to stop -- when it returns true when applied to one + of these seed values. ++ </li> + <li> <var>F</var> maps each seed value to a character. These characters are added + to the base character set <var>base-cs</var> to form the result; <var>base-cs</var> defaults to + the empty set. <code>char-set-unfold!</code> adds the characters to <var>base-cs</var> in a + linear-update -- it is allowed, but not required, to side-effect + and use <var>base-cs</var>'s storage to construct the result. ++ </li> + </ul> +- +- <p> ++<p> + More precisely, the following definitions hold, ignoring the + optional-argument issues: +- +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (define (char-set-unfold p f g seed base-cs) + (char-set-unfold! p f g seed (char-set-copy base-cs))) + +@@ -742,31 +835,34 @@ with + (lp (g seed) ; Loop on (G SEED). + (char-set-adjoin! cs (f seed)))))) ; Add (F SEED) to set. + </pre> +- ++<p> + (Note that the actual implementation may be more efficient.) +- +- <p> ++</p> ++<p> + Examples: +-<pre class=code-example> +-(port->char-set p) = (char-set-unfold eof-object? values ++</p> ++<pre class="code-example"> ++(port->char-set p) = (char-set-unfold eof-object? values + (lambda (x) (read-char p)) + (read-char p)) + +-(list->char-set lis) = (char-set-unfold null? car cdr lis) ++(list->char-set lis) = (char-set-unfold null? car cdr lis) + </pre> ++</dd> + <!-- + ==== char-set-for-each + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set-for-each"></a> +-<code class=proc-def>char-set-for-each</code><var> proc cs -> unspecified</var> +-<dd class=proc-def> ++<dt class="proc-def" id="char-set-for-each"> ++<code class="proc-def">char-set-for-each</code><var> proc cs -> unspecified</var> ++</dt> ++<dd class="proc-def"> ++<p> + Apply procedure <var>proc</var> to each character in the character set <var>cs</var>. + Note that the order in which <var>proc</var> is applied to the characters in the + set is not specified, and may even change from one procedure application + to another. +- +- <p> ++</p> ++<p> + Nothing at all is specified about the value returned by this procedure; it + is not even required to be consistent from call to call. It is simply + required to be a value (or values) that may be passed to a command +@@ -776,123 +872,137 @@ with + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr>, + this restricts the procedure to returning a single value; + non-R5RS systems may not even provide this restriction. +- ++</p> ++</dd> + <!-- + ==== char-set-map + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set-map"></a> +-<code class=proc-def>char-set-map</code><var> proc cs -> char-set</var> +-<dd class=proc-def> +- <var>proc</var> is a char->char procedure. Apply it to all the characters in ++<dt class="proc-def" id="char-set-map"> ++<code class="proc-def">char-set-map</code><var> proc cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> ++ <var>proc</var> is a char->char procedure. Apply it to all the characters in + the char-set <var>cs</var>, and collect the results into a new character set. +- +- <p> +- Essentially lifts <var>proc</var> from a char->char procedure to a char-set -> ++</p> ++<p> ++ Essentially lifts <var>proc</var> from a char->char procedure to a char-set -> + char-set procedure. +- +- <p> ++</p> ++<p> + Example: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-set-map char-downcase cset) + </pre> ++</dd> + </dl> + +- + <!--========================================================================--> +-<h2><a name="Creating">Creating character sets</a></h2> ++<h2 id="Creating">Creating character sets</h2> + <dl> + + <!-- + ==== char-set-copy + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set-copy"></a> +-<code class=proc-def>char-set-copy</code><var> cs -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def" id="char-set-copy"> ++<code class="proc-def">char-set-copy</code><var> cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns a copy of the character set <var>cs</var>. "Copy" means that if either the + input parameter or the result value of this procedure is passed to one of + the linear-update procedures described below, the other character set is + guaranteed not to be altered. +- +- <p> ++</p> ++<p> + A system that provides pure-functional implementations of the + linear-operator suite could implement this procedure as the identity + function -- so copies are <em>not</em> guaranteed to be distinct by <code>eq?</code>. +- ++</p> ++</dd> + <!-- + ==== char-set + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set"></a> +-<code class=proc-def>char-set</code><var> char<sub>1</sub> ... -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def" id="char-set"> ++<code class="proc-def">char-set</code><var> char<sub>1</sub> ... -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return a character set containing the given characters. +- ++</p> ++</dd> + <!-- + ==== list->char-set list->char-set + ============================================================================--> +-<dt class=proc-def1> +-<a name="list->char-set"></a> +-<a name="list->char-set!"></a> +-<code class=proc-def>list->char-set </code><var> char-list [base-cs] -> char-set</var> +-<dt class=proc-defn><code class=proc-def>list->char-set!</code><var> char-list base-cs -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="list->char-set"> ++<code class="proc-def">list->char-set </code><var> char-list [base-cs] -> char-set</var> ++</dt> ++<dt class="proc-defn" id="list->char-set!"><code class="proc-def">list->char-set!</code><var> char-list base-cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return a character set containing the characters in the list of + characters <var>char-list</var>. +- +- <p> ++</p> ++<p> + If character set <var>base-cs</var> is provided, the characters from <var>char-list</var> +- are added to it. <code>list->char-set!</code> is allowed, but not required, ++ are added to it. <code>list->char-set!</code> is allowed, but not required, + to side-effect and reuse the storage in <var>base-cs</var>; +- <code>list->char-set</code> produces a fresh character set. +- ++ <code>list->char-set</code> produces a fresh character set. ++</p> ++</dd> + <!-- + ==== string->char-set string->char-set! + ============================================================================--> +-<dt class=proc-def1> +-<a name="string->char-set"></a> +-<a name="string->char-set!"></a> +-<code class=proc-def>string->char-set </code><var> s [base-cs] -> char-set</var> +-<dt class=proc-defn><code class=proc-def>string->char-set!</code><var> s base-cs -> char-set</var> +-<dd class=proc-def> +- ++<dt class="proc-def1"> ++<a name="string->char-set"></a> ++<a name="string->char-set!"></a> ++<code class="proc-def">string->char-set </code><var> s [base-cs] -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">string->char-set!</code><var> s base-cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Return a character set containing the characters in the string <var>s</var>. +- +- <p> ++</p> ++<p> + If character set <var>base-cs</var> is provided, the characters from <var>s</var> are added to +- it. <code>string->char-set!</code> is allowed, but not required, to side-effect and +- reuse the storage in <var>base-cs</var>; <code>string->char-set</code> produces a fresh character ++ it. <code>string->char-set!</code> is allowed, but not required, to side-effect and ++ reuse the storage in <var>base-cs</var>; <code>string->char-set</code> produces a fresh character + set. +- ++</p> ++</dd> + <!-- + ==== char-set-filter char-set-filter! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="char-set-filter"></a> + <a name="char-set-filter!"></a> +-<code class=proc-def>char-set-filter </code><var> pred cs [base-cs] -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-filter!</code><var> pred cs base-cs -> char-set</var> +-<dd class=proc-def> +- ++<code class="proc-def">char-set-filter </code><var> pred cs [base-cs] -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">char-set-filter!</code><var> pred cs base-cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns a character set containing every character <var>c</var> + in <var>cs</var> such that <code>(<var>pred</var> <var>c</var>)</code> + returns true. +- ++</p> + <p> + If character set <var>base-cs</var> is provided, the characters specified + by <var>pred</var> are added to it. + <code>char-set-filter!</code> is allowed, but not required, + to side-effect and reuse the storage in <var>base-cs</var>; + <code>char-set-filter</code> produces a fresh character set. +- ++</p> + <p> + An implementation may not save away a reference to <var>pred</var> and + invoke it after <code>char-set-filter</code> or + <code>char-set-filter!</code> returns -- that is, "lazy," + on-demand implementations are not allowed, as <var>pred</var> may have + external dependencies on mutable data or have other side-effects. +- ++</p> + <p> + Rationale: This procedure provides a means of converting a character + predicate into its equivalent character set; the <var>cs</var> parameter +@@ -900,52 +1010,56 @@ with + be aware that filtering a character set such as <code>char-set:full</code> + could be a very expensive operation in an implementation that provided an + extremely large character type, such as 32-bit Unicode. An earlier draft +- of this library provided a simple <code>predicate->char-set</code> ++ of this library provided a simple <code>predicate->char-set</code> + procedure, which was rejected in favor of <code>char-set-filter</code> for + this reason. +- ++</p> ++</dd> + + <!-- + ==== ucs-range->char-set ucs-range->char-set! + ============================================================================--> +-<dt class=proc-def1> +-<a name="ucs-range->char-set"></a> +-<a name="ucs-range->char-set!"></a> +-<code class=proc-def>ucs-range->char-set </code><var> lower upper [error? base-cs] -> char-set</var> +-<dt class=proc-defn><code class=proc-def>ucs-range->char-set!</code><var> lower upper error? base-cs -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def1"> ++<a name="ucs-range->char-set"></a> ++<a name="ucs-range->char-set!"></a> ++<code class="proc-def">ucs-range->char-set </code><var> lower upper [error? base-cs] -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">ucs-range->char-set!</code><var> lower upper error? base-cs -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + <var>Lower</var> and <var>upper</var> are exact non-negative integers; +- <var>lower</var> <= <var>upper</var>. +- +- <p> ++ <var>lower</var> <= <var>upper</var>. ++</p> ++<p> + Returns a character set containing every character whose ISO/IEC 10646 + UCS-4 code lies in the half-open range [<var>lower</var>,<var>upper</var>). +- ++</p> + <ul> + <li> If the requested range includes unassigned UCS values, these are + silently ignored (the current UCS specification has "holes" in the + space of assigned codes). +- ++ </li> + <li> If the requested range includes "private" or "user space" codes, these + are handled in an implementation-specific manner; however, a UCS- or + Unicode-based Scheme implementation should pass them through + transparently. +- ++ </li> + <li> If any code from the requested range specifies a valid, assigned + UCS character that has no corresponding representative in the + implementation's character type, then (1) an error is raised if <var>error?</var> + is true, and (2) the code is ignored if <var>error?</var> is false (the default). + This might happen, for example, if the implementation uses ASCII + characters, and the requested range includes non-ASCII characters. ++ </li> + </ul> +- +- <p> ++<p> + If character set <var>base-cs</var> is provided, the characters specified by the +- range are added to it. <code>ucs-range->char-set!</code> is allowed, but not required, ++ range are added to it. <code>ucs-range->char-set!</code> is allowed, but not required, + to side-effect and reuse the storage in <var>base-cs</var>; +- <code>ucs-range->char-set</code> produces a fresh character set. +- +- <p> ++ <code>ucs-range->char-set</code> produces a fresh character set. ++</p> ++<p> + Note that ASCII codes are a subset of the Latin-1 codes, which are in turn + a subset of the 16-bit Unicode codes, which are themselves a subset of the + 32-bit UCS-4 codes. We commit to a specific encoding in this routine, +@@ -954,14 +1068,17 @@ with + implementation may use EBCDIC or SHIFT-JIS to encode characters; it must + simply map the UCS characters from the given range into the native + representation when possible, and report errors when not possible. +- ++</p> ++</dd> + <!-- + ==== ->char-set + ============================================================================--> +-<dt class=proc-def> +-<a name="->char-set"></a> +-<code class=proc-def>->char-set</code><var> x -> char-set</var> +-<dd class=proc-def> ++<dt class="proc-def"> ++<a name="->char-set"></a> ++<code class="proc-def">->char-set</code><var> x -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Coerces <var>x</var> into a char-set. + <var>X</var> may be a string, character or + char-set. A string is converted to the set of its constituent characters; +@@ -969,76 +1086,94 @@ with + as-is. + This procedure is intended for use by other procedures that want to + provide "user-friendly," wide-spectrum interfaces to their clients. +- ++</p> ++</dd> + </dl> +- + <!--========================================================================--> +-<h2><a name="Querying">Querying character sets</a></h2> ++<h2 id="Querying">Querying character sets</h2> + <dl> + + <!-- + ==== char-set-size + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-size"></a> +-<code class=proc-def>char-set-size</code><var> cs -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-size</code><var> cs -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Returns the number of elements in character set <var>cs</var>. +- ++</p> ++</dd> + <!-- + ==== char-set-count + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-count"></a> +-<code class=proc-def>char-set-count</code><var> pred cs -> integer</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-count</code><var> pred cs -> integer</var> ++</dt> ++<dd class="proc-def"> ++<p> + Apply <var>pred</var> to the chars of character set <var>cs</var>, and return the number + of chars that caused the predicate to return true. +- ++</p> ++</dd> + <!-- + ==== char-set->list + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set->list"></a> +-<code class=proc-def>char-set->list</code><var> cs -> character-list</var> +-<dd class=proc-def> ++<dt class="proc-def"> ++<a name="char-set->list"></a> ++<code class="proc-def">char-set->list</code><var> cs -> character-list</var> ++</dt> ++<dd class="proc-def"> ++<p> + This procedure returns a list of the members of character set <var>cs</var>. + The order in which <var>cs</var>'s characters appear in the list is not defined, + and may be different from one call to another. +- ++</p> ++</dd> + <!-- + ==== char-set->string + ============================================================================--> +-<dt class=proc-def> +-<a name="char-set->string"></a> +-<code class=proc-def>char-set->string</code><var> cs -> string</var> +-<dd class=proc-def> ++<dt class="proc-def"> ++<a name="char-set->string"></a> ++<code class="proc-def">char-set->string</code><var> cs -> string</var> ++</dt> ++<dd class="proc-def"> ++<p> + This procedure returns a string containing the members of character set <var>cs</var>. + The order in which <var>cs</var>'s characters appear in the string is not defined, + and may be different from one call to another. +- ++</p> ++</dd> + <!-- + ==== char-set-contains? + ============================================================================--> +-<dt class=proc-def> ++<dt class="proc-def"> + <a name="char-set-contains-p"></a> +-<code class=proc-def>char-set-contains?</code><var> cs char -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-contains?</code><var> cs char -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + This procedure tests <var>char</var> for membership in character set <var>cs</var>. +- +- <p> ++</p> ++<p> + The MIT Scheme character-set package called this procedure + <var>char-set-member?</var>, but the argument order isn't consistent with the name. +- ++</p> ++</dd> + <!-- + ==== char-set-every char-set-any + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="char-set-every"></a> + <a name="char-set-any"></a> +-<code class=proc-def>char-set-every</code><var> pred cs -> boolean</var> +-<dt class=proc-defn><code class=proc-def>char-set-any </code><var> pred cs -> boolean</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-every</code><var> pred cs -> boolean</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">char-set-any </code><var> pred cs -> boolean</var> ++</dt> ++<dd class="proc-def"> ++<p> + The <code>char-set-every</code> procedure returns true if predicate <var>pred</var> + returns true of every character in the character set <var>cs</var>. + Likewise, <code>char-set-any</code> applies <var>pred</var> to every character in +@@ -1046,169 +1181,171 @@ with + If no character produces a true value, it returns false. + The order in which these procedures sequence through the elements of + <var>cs</var> is not specified. +- +- <p> ++</p> ++<p> + Note that if you need to determine the actual character on which a + predicate returns true, use <code>char-set-any</code> and arrange for the predicate + to return the character parameter as its true value, <em>e.g.</em> +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (char-set-any (lambda (c) (and (char-upper-case? c) c)) + cs) + </pre> ++</dd> + </dl> +- + <!--========================================================================--> +-<h2><a name="Algebra">Character-set algebra</a></h2> ++<h2 id="Algebra">Character-set algebra</h2> + <dl> + + <!-- + ==== char-set-adjoin char-set-delete + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="char-set-adjoin"></a> + <a name="char-set-delete"></a> +-<code class=proc-def>char-set-adjoin</code><var> cs char<sub>1</sub> ... -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-delete</code><var> cs char<sub>1</sub> ... -> char-set</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-adjoin</code><var> cs char<sub>1</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">char-set-delete</code><var> cs char<sub>1</sub> ... -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Add/delete the <var>char<sub>i</sub></var> characters to/from character set <var>cs</var>. +- ++</p> ++</dd> + <!-- + ==== char-set-adjoin! char-set-delete! + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="char-set-adjoin!"></a> + <a name="char-set-delete!"></a> +-<code class=proc-def>char-set-adjoin!</code><var> cs char<sub>1</sub> ... -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-delete!</code><var> cs char<sub>1</sub> ... -> char-set</var> +-<dd class=proc-def> +- ++<code class="proc-def">char-set-adjoin!</code><var> cs char<sub>1</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">char-set-delete!</code><var> cs char<sub>1</sub> ... -> char-set</var> ++</dt> ++<dd class="proc-def"> ++<p> + Linear-update variants. These procedures are allowed, but not + required, to side-effect their first parameter. +- ++</p> ++</dd> + <!-- + ==== char-set-complement char-set-union char-set-intersection + ==== char-set-difference char-set-xor char-set-diff+intersection + ============================================================================--> +-<dt class=proc-def1> ++<dt class="proc-def1"> + <a name="char-set-complement"></a> + <a name="char-set-union"></a> + <a name="char-set-intersection"></a> + <a name="char-set-difference"></a> + <a name="char-set-xor"></a> + <a name="char-set-diff+intersection"></a> +-<code class=proc-def>char-set-complement</code><var> cs -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-union</code><var> cs<sub>1</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-intersection</code><var> cs<sub>1</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-difference</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-xor</code><var> cs<sub>1</sub> ... -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-diff+intersection</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> [char-set char-set]</var> +-<dd class=proc-def> ++<code class="proc-def">char-set-complement</code><var> cs -> char-set</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">char-set-union</code><var> cs<sub>1</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">char-set-intersection</code><var> cs<sub>1</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">char-set-difference</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi"><code class="proc-def">char-set-xor</code><var> cs<sub>1</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defn"><code class="proc-def">char-set-diff+intersection</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> [char-set char-set]</var> ++</dt> ++<dd class="proc-def"> ++<p> + These procedures implement set complement, union, intersection, + difference, and exclusive-or for character sets. The union, intersection + and xor operations are n-ary. The difference function is also n-ary, + associates to the left (that is, it computes the difference between + its first argument and the union of all the other arguments), + and requires at least one argument. +- +- <p> ++</p> ++<p> + Boundary cases: +-<pre class=code-example> +-(char-set-union) => char-set:empty +-(char-set-intersection) => char-set:full +-(char-set-xor) => char-set:empty +-(char-set-difference <var>cs</var>) => <var>cs</var> ++</p> ++<pre class="code-example"> ++(char-set-union) => char-set:empty ++(char-set-intersection) => char-set:full ++(char-set-xor) => char-set:empty ++(char-set-difference <var>cs</var>) => <var>cs</var> + </pre> +- +- <p> ++<p> + <code>char-set-diff+intersection</code> returns both the difference and the + intersection of the arguments -- it partitions its first parameter. + It is equivalent to +-<pre class=code-example> ++</p> ++<pre class="code-example"> + (values (char-set-difference <var>cs<sub>1</sub></var> <var>cs<sub>2</sub></var> ...) + (char-set-intersection <var>cs<sub>1</sub></var> (char-set-union <var>cs<sub>2</sub></var> ...))) + </pre> ++<p> + but can be implemented more efficiently. +- ++</p> + <p> + Programmers should be aware that <code>char-set-complement</code> could potentially + be a very expensive operation in Scheme implementations that provide + a very large character type, such as 32-bit Unicode. If this is a + possibility, sets can be complimented with respect to a smaller + universe using <code>char-set-difference</code>. +- +- ++</p> ++</dd> + <!-- + ==== char-set-complement! char-set-union! char-set-intersection! + ==== char-set-difference! char-set-xor! char-set-diff+intersection! + ============================================================================--> +-<dt class=proc-def1> +-<a name="char-set-complement!"></a> +-<a name="char-set-union!"></a> +-<a name="char-set-intersection!"></a> +-<a name="char-set-difference!"></a> +-<a name="char-set-xor!"></a> +-<a name="char-set-diff+intersection!"></a> +-<code class=proc-def>char-set-complement!</code><var> cs -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-union!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-intersection!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-difference!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> +-<dt class=proc-defi><code class=proc-def>char-set-xor!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> +-<dt class=proc-defn><code class=proc-def>char-set-diff+intersection!</code><var> cs<sub>1</sub> cs<sub>2</sub> cs<sub>3</sub> ... -> [char-set char-set]</var> +-<dd class=proc-def> ++<dt class="proc-def1" id="char-set-complement!"> ++<code class="proc-def">char-set-complement!</code><var> cs -> char-set</var> ++</dt> ++<dt class="proc-defi" id="char-set-union!"><code class="proc-def">char-set-union!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi" id="char-set-intersection!"><code class="proc-def">char-set-intersection!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi" id="char-set-difference!"><code class="proc-def">char-set-difference!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defi" id="char-set-xor!"><code class="proc-def">char-set-xor!</code><var> cs<sub>1</sub> cs<sub>2</sub> ... -> char-set</var> ++</dt> ++<dt class="proc-defn" id="char-set-diff+intersection!"><code class="proc-def">char-set-diff+intersection!</code><var> cs<sub>1</sub> cs<sub>2</sub> cs<sub>3</sub> ... -> [char-set char-set]</var> ++</dt> ++<dd class="proc-def"> ++<p> + These are linear-update variants of the set-algebra functions. + They are allowed, but not required, to side-effect their first (required) + parameter. +- +- <p> ++</p> ++<p> + <code>char-set-diff+intersection!</code> is allowed to side-effect both + of its two required parameters, <var>cs<sub>1</sub></var> + and <var>cs<sub>2</sub></var>. ++</p> ++</dd> + </dl> + + <!--========================================================================--> +-<h2><a name="StandardCharsets">Standard character sets</a></h2> ++<h2 id="StandardCharsets">Standard character sets</h2> + <p> + Several character sets are predefined for convenience: +-<a name="char-set:lower-case"></a> +-<a name="char-set:lower-case"></a> +-<a name="char-set:upper-case"></a> +-<a name="char-set:title-case"></a> +-<a name="char-set:letter"></a> +-<a name="char-set:digit"></a> +-<a name="char-set:letter+digit"></a> +-<a name="char-set:graphic"></a> +-<a name="char-set:printing"></a> +-<a name="char-set:whitespace"></a> +-<a name="char-set:iso-control"></a> +-<a name="char-set:punctuation"></a> +-<a name="char-set:symbol"></a> +-<a name="char-set:hex-digit"></a> +-<a name="char-set:blank"></a> +-<a name="char-set:ascii"></a> +-<a name="char-set:empty"></a> +-<a name="char-set:full"></a> +-<div class=inset> +-<table cellpadding=0 cellspacing=0> +-<tr><td><code>char-set:lower-case</code> </td><td>Lower-case letters</td></tr> +-<tr><td><code>char-set:upper-case</code> </td><td>Upper-case letters</td></tr> +-<tr><td><code>char-set:title-case</code> </td><td>Title-case letters</td></tr> +-<tr><td><code>char-set:letter</code> </td><td>Letters</td></tr> +-<tr><td><code>char-set:digit</code> </td><td>Digits</td></tr> +-<tr><td><code>char-set:letter+digit</code> </td><td>Letters and digits</td></tr> +-<tr><td><code>char-set:graphic</code> </td><td>Printing characters except spaces</td></tr> +-<tr><td><code>char-set:printing</code> </td><td>Printing characters including spaces</td></tr> +-<tr><td><code>char-set:whitespace</code> </td><td>Whitespace characters </td></tr> +-<tr><td><code>char-set:iso-control</code> </td><td>The ISO control characters </td></tr> +-<tr><td><code>char-set:punctuation</code> </td><td>Punctuation characters</td></tr> +-<tr><td><code>char-set:symbol</code> </td><td>Symbol characters</td></tr> +-<tr><td><code>char-set:hex-digit</code> </td><td>A hexadecimal digit: 0-9, A-F, a-f </td></tr> +-<tr><td><code>char-set:blank</code> </td><td>Blank characters -- horizontal whitespace</td></tr> +-<tr><td><code>char-set:ascii</code> </td><td>All characters in the ASCII set. </td></tr> +-<tr><td><code>char-set:empty</code> </td><td>Empty set </td></tr> +-<tr><td><code>char-set:full</code> </td><td>All characters </td></tr> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> ++<tr id="char-set:lower-case"><td><code>char-set:lower-case</code> </td><td>Lower-case letters</td></tr> ++<tr id="char-set:upper-case"><td><code>char-set:upper-case</code> </td><td>Upper-case letters</td></tr> ++<tr id="char-set:title-case"><td><code>char-set:title-case</code> </td><td>Title-case letters</td></tr> ++<tr id="char-set:letter"><td><code>char-set:letter</code> </td><td>Letters</td></tr> ++<tr id="char-set:digit"><td><code>char-set:digit</code> </td><td>Digits</td></tr> ++<tr id="char-set:letter+digit"><td><code>char-set:letter+digit</code> </td><td>Letters and digits</td></tr> ++<tr id="char-set:graphic"><td><code>char-set:graphic</code> </td><td>Printing characters except spaces</td></tr> ++<tr id="char-set:printing"><td><code>char-set:printing</code> </td><td>Printing characters including spaces</td></tr> ++<tr id="char-set:whitespace"><td><code>char-set:whitespace</code> </td><td>Whitespace characters </td></tr> ++<tr id="char-set:iso-control"><td><code>char-set:iso-control</code> </td><td>The ISO control characters </td></tr> ++<tr id="char-set:punctuation"><td><code>char-set:punctuation</code> </td><td>Punctuation characters</td></tr> ++<tr id="char-set:symbol"><td><code>char-set:symbol</code> </td><td>Symbol characters</td></tr> ++<tr id="char-set:hex-digit"><td><code>char-set:hex-digit</code> </td><td>A hexadecimal digit: 0-9, A-F, a-f </td></tr> ++<tr id="char-set:blank"><td><code>char-set:blank</code> </td><td>Blank characters -- horizontal whitespace</td></tr> ++<tr id="char-set:ascii"><td><code>char-set:ascii</code> </td><td>All characters in the ASCII set. </td></tr> ++<tr id="char-set:empty"><td><code>char-set:empty</code> </td><td>Empty set </td></tr> ++<tr id="char-set:full"><td><code>char-set:full</code> </td><td>All characters </td></tr> + </table> + </div> +- + <p> + Note that there may be characters in <code>char-set:letter</code> that are neither upper or + lower case---this might occur in implementations that use a character type +@@ -1216,8 +1353,9 @@ richer than ASCII, such as Unicode. A "graphic character" is one that would + put ink on your page. While the exact composition of these sets may vary + depending upon the character type provided by the underlying Scheme system, + here are the definitions for some of the sets in an ASCII implementation: +-<div class=inset> +-<table cellpadding=0 cellspacing=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td><code>char-set:lower-case</code> </td><td>a-z </td></tr> + <tr><td><code>char-set:upper-case</code> </td><td>A-Z </td></tr> + <tr><td><code>char-set:letter</code> </td><td>A-Z and a-z </td></tr> +@@ -1232,76 +1370,93 @@ here are the definitions for some of the sets in an ASCII implementation: + <tr><td><code>char-set:iso-control</code> </td><td>ASCII 0-31 and 127 </td></tr> + </table> + </div> +- + <p> + Note that the existence of the <code>char-set:ascii</code> set implies that the underlying + character set is required to be at least as rich as ASCII (including + ASCII's control characters). +- ++</p> + <p> + Rationale: The name choices reflect a shift from the older "alphabetic/numeric" + terms found in + <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> + and Posix to newer, Unicode-influenced "letter/digit" lexemes. +- ++</p> + <!--========================================================================--> +-<h1><a name="StandardCharsetDefs"> +- Unicode, Latin-1 and ASCII definitions of the standard character sets</a> +-</h1> ++<h2 id="StandardCharsetDefs"> ++ Unicode, Latin-1 and ASCII definitions of the standard character sets ++</h2> + <p> + In Unicode Scheme implementations, the base character sets are compatible with +-Java's Unicode specifications. For ASCII or Latin-1, we simply restrict the ++Java's Unicode specifications. ++<!-- Commented out until Olin approves ++[<i>2019 note: However, implementers of Unicode are urged to see ++<a href="#PostFinalizationNote1">Post-Finalization Note 1</a> ++if they have not already done so, ++and then skip the rest of this section.</i>] ++--> ++</p> ++<p>For ASCII or Latin-1, we simply restrict the + Unicode set specifications to their first 128 or 256 codes, respectively. + Scheme implementations that are not based on ASCII, Latin-1 or Unicode should + attempt to preserve the sense or spirit of these definitions. +- ++</p> + <p> + The following descriptions frequently make reference to the "Unicode character + database." This is a file, available at URL +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt"> + ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> + </div> +-<p class=continue> ++<p class="continue"> + Each line contains a description of a Unicode character. The first + semicolon-delimited field of the line gives the hex value of the character's + code; the second field gives the name of the character, and the third field + gives a two-letter category. Other fields give simple 1-1 case-mappings for + the character and other information; see +-<div class=inset> ++</p> ++<div class="inset"> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html"> + ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html</a> + </div> +-<p class=continue> ++<p class="continue"> + for further description of the file's format. Note in particular the +-two-letter category specified in the third field, which is referenced ++two-letter category specified in the the third field, which is referenced + frequently in the descriptions below. +- ++</p> + <!--========================================================================--> +-<h2><a name="lower-case-def">char-set:lower-case</a></h2> ++<h2 id="lower-case-def">char-set:lower-case</h2> + <p> + For Unicode, we follow Java's specification: a character is lowercase if ++</p> + <ul> +-<li> it is not in the range [U+2000,U+2FFF], and +-<li> the Unicode attribute table does not give a lowercase mapping for it, and +-<li> at least one of the following is true: +- <ul> +- <li> the Unicode attribute table gives a mapping to uppercase +- for the character, or +- <li> the name for the character in the Unicode attribute table contains ++ <li> it is not in the range [U+2000,U+2FFF], and ++ </li> ++ <li> the Unicode attribute table does not give a lowercase mapping for it, and ++ </li> ++ <li> at least one of the following is true: ++ <ul> ++ <li> the Unicode attribute table gives a mapping to uppercase ++ for the character, or ++ </li> ++ <li> the name for the character in the Unicode attribute table contains + the words "SMALL LETTER" or "SMALL LIGATURE". +- </ul> ++ </li> ++ </ul> ++ </li> + </ul> + + <p> + The lower-case ASCII characters are +-<div class=inset> ++</p> ++<div class="inset"> + abcdefghijklmnopqrstuvwxyz + </div> +-<p class=continue> ++<p class="continue"> + Latin-1 adds another 33 lower-case characters to the ASCII set: +-<div class=inset> +-<table cellpadding=0 cellspacing=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00B5</td> <td>MICRO SIGN</td></tr> + <tr><td>00DF</td> <td>LATIN SMALL LETTER SHARP S</td></tr> + <tr><td>00E0</td> <td>LATIN SMALL LETTER A WITH GRAVE</td></tr> +@@ -1337,38 +1492,41 @@ Latin-1 adds another 33 lower-case characters to the ASCII set: + <tr><td>00FF</td> <td>LATIN SMALL LETTER Y WITH DIAERESIS</td></tr> + </table> + </div> +-<p class=continue> ++<p class="continue"> + Note that three of these have no corresponding Latin-1 upper-case character: +-<div class=inset> +-<table cellpadding=0 cellspacing=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00B5</td> <td>MICRO SIGN</td></tr> + <tr><td>00DF</td> <td>LATIN SMALL LETTER SHARP S</td></tr> + <tr><td>00FF</td> <td>LATIN SMALL LETTER Y WITH DIAERESIS</td></tr> + </table> + </div> +-<p class=continue> ++<p class="continue"> + (The compatibility micro character uppercases to the non-Latin-1 Greek capital + mu; the German sharp s character uppercases to the pair of characters "SS," + and the capital y-with-diaeresis is non-Latin-1.) +- ++</p> + <p> + (Note that the Java spec for lowercase characters given at +-<div class=inset> ++</p> ++<div class="inset"> + <a href="http://java.sun.com/docs/books/jls/html/javalang.doc4.html#14345"> + http://java.sun.com/docs/books/jls/html/javalang.doc4.html#14345</a> + </div> +-<p class=continue> ++<p class="continue"> + is inconsistent. U+00B5 MICRO SIGN fulfills the requirements for a lower-case + character (as of Unicode 3.0), but is not given in the numeric list of + lower-case character codes.) +- ++</p> + <p> + (Note that the Java spec for <code>isLowerCase()</code> given at +-<div class=inset> ++</p> ++<div class="inset"> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html#isLowerCase(char)"> + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html#isLowerCase(char)</a> + </div> +-<p class=continue> ++<p class="continue"> + gives three mutually inconsistent definitions of "lower case." The first is + the definition used in this SRFI. Following text says "A character is + considered to be lowercase if and only if it is specified to be lowercase by +@@ -1377,33 +1535,41 @@ file)." The former spec excludes U+00AA FEMININE ORDINAL INDICATOR and + U+00BA MASCULINE ORDINAL INDICATOR; the later spec includes them. Finally, + the spec enumerates a list of characters in the Latin-1 subset; this list + excludes U+00B5 MICRO SIGN, which is included in both of the previous specs.) +- ++</p> + <!--========================================================================--> +-<h2><a name="upper-case-def">char-set:upper-case</a></h2> ++<h2 id="upper-case-def">char-set:upper-case</h2> + <p> + For Unicode, we follow Java's specification: a character is uppercase if ++</p> + <ul> +-<li> it is not in the range [U+2000,U+2FFF], and +-<li> the Unicode attribute table does not give an uppercase mapping for it ++ <li> it is not in the range [U+2000,U+2FFF], and ++ </li> ++ <li> the Unicode attribute table does not give an uppercase mapping for it + (this excludes titlecase characters), and +-<li> at least one of the following is true: +- <ul> +- <li> the Unicode attribute table gives a mapping to lowercase ++ </li> ++ <li> at least one of the following is true: ++ <ul> ++ <li> the Unicode attribute table gives a mapping to lowercase + for the character, or +- <li> the name for the character in the Unicode attribute table contains ++ </li> ++ <li> the name for the character in the Unicode attribute table contains + the words "CAPITAL LETTER" or "CAPITAL LIGATURE". +- </ul> ++ </li> ++ </ul> ++ </li> + </ul> + + <p> + The upper-case ASCII characters are +-<div class=inset> ++</p> ++<div class="inset"> + ABCDEFGHIJKLMNOPQRSTUVWXYZ + </div> +-<p class=continue> ++<p class="continue"> + Latin-1 adds another 30 upper-case characters to the ASCII set: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00C0</td> <td>LATIN CAPITAL LETTER A WITH GRAVE</td></tr> + <tr><td>00C1</td> <td>LATIN CAPITAL LETTER A WITH ACUTE</td></tr> + <tr><td>00C2</td> <td>LATIN CAPITAL LETTER A WITH CIRCUMFLEX</td></tr> +@@ -1437,109 +1603,112 @@ Latin-1 adds another 30 upper-case characters to the ASCII set: + </table> + </div> + <!--========================================================================--> +-<h2><a name="title-case-def">char-set:title-case</a></h2> ++<h2 id="title-case-def">char-set:title-case</h2> + <p> + In Unicode, a character is titlecase if it has the category Lt in + the character attribute database. There are very few of these characters; + here is the entire 31-character list as of Unicode 3.0: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> +-<tr><td>01C5 </td><td nowrap> LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> ++<tr><td>01C5 </td><td nowrap="nowrap"> LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON + </td></tr> +-<tr><td>01C8 </td><td nowrap> LATIN CAPITAL LETTER L WITH SMALL LETTER J ++<tr><td>01C8 </td><td nowrap="nowrap"> LATIN CAPITAL LETTER L WITH SMALL LETTER J + </td></tr> +-<tr><td>01CB </td><td nowrap> LATIN CAPITAL LETTER N WITH SMALL LETTER J ++<tr><td>01CB </td><td nowrap="nowrap"> LATIN CAPITAL LETTER N WITH SMALL LETTER J + </td></tr> +-<tr><td>01F2 </td><td nowrap> LATIN CAPITAL LETTER D WITH SMALL LETTER Z ++<tr><td>01F2 </td><td nowrap="nowrap"> LATIN CAPITAL LETTER D WITH SMALL LETTER Z + </td></tr> +-<tr><td>1F88 </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI ++<tr><td>1F88 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F89 </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI ++<tr><td>1F89 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8A </td><td nowrap>GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI ++<tr><td>1F8A </td><td nowrap="nowrap">GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8B </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI ++<tr><td>1F8B </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8C </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI ++<tr><td>1F8C </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8D </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI ++<tr><td>1F8D </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8E </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1F8E </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F8F </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1F8F </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F98 </td><td nowrap> GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI ++<tr><td>1F98 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F99 </td><td nowrap> GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI ++<tr><td>1F99 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9A </td><td nowrap> GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI ++<tr><td>1F9A </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9B </td><td nowrap> GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI ++<tr><td>1F9B </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9C </td><td nowrap> GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI ++<tr><td>1F9C </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9D </td><td nowrap> GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI ++<tr><td>1F9D </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9E </td><td nowrap> GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1F9E </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1F9F </td><td nowrap> GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1F9F </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FA8 </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI ++<tr><td>1FA8 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FA9 </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI ++<tr><td>1FA9 </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAA </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI ++<tr><td>1FAA </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAB </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI ++<tr><td>1FAB </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAC </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI ++<tr><td>1FAC </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAD </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI ++<tr><td>1FAD </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAE </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1FAE </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FAF </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI ++<tr><td>1FAF </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + </td></tr> +-<tr><td>1FBC </td><td nowrap> GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI ++<tr><td>1FBC </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + </td></tr> +-<tr><td>1FCC </td><td nowrap> GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI ++<tr><td>1FCC </td><td nowrap="nowrap"> GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + </td></tr> +-<tr><td>1FFC </td><td nowrap> GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI ++<tr><td>1FFC </td><td nowrap="nowrap"> GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + </td></tr> + </table> + </div> + <p> + There are no ASCII or Latin-1 titlecase characters. +- ++</p> + + <!--========================================================================--> +-<h2><a name="letter-def">char-set:letter</a></h2> ++<h2 id="letter-def">char-set:letter</h2> + <p> + In Unicode, a letter is any character with one of the letter categories + (Lu, Ll, Lt, Lm, Lo) in the Unicode character database. +- ++</p> + <p> + There are 52 ASCII letters +-<div class=indent> +- abcdefghijklmnopqrstuvwxyz <br> +- ABCDEFGHIJKLMNOPQRSTUVWXYZ <br> ++</p> ++<div class="indent"> ++ abcdefghijklmnopqrstuvwxyz <br /> ++ ABCDEFGHIJKLMNOPQRSTUVWXYZ <br /> + </div> + <p> + There are 117 Latin-1 letters. These are the 115 characters that are + members of the Latin-1 <code>char-set:lower-case</code> and <code>char-set:upper-case</code> sets, + plus +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00AA</td> <td>FEMININE ORDINAL INDICATOR</td></tr> + <tr><td>00BA</td> <td>MASCULINE ORDINAL INDICATOR</td></tr> + </table> + </div> +-<p class=continue> ++<p class="continue"> + (These two letters are considered lower-case by Unicode, but not by + Java or SRFI 14.) +- ++</p> + <!--========================================================================--> +-<h2><a name="digit-def">char-set:digit</a></h2> ++<h2 id="digit-def">char-set:digit</h2> + + <p> + In Unicode, a character is a digit if it has the category Nd in +@@ -1547,26 +1716,27 @@ the character attribute database. In Latin-1 and ASCII, the only + such characters are 0123456789. In Unicode, there are other digit + characters in other code blocks, such as Gujarati digits and Tibetan + digits. +- ++</p> + + <!--========================================================================--> +-<h2><a name="hex-digit-def">char-set:hex-digit</a></h2> ++<h2 id="hex-digit-def">char-set:hex-digit</h2> + <p> + The only hex digits are 0123456789abcdefABCDEF. +- ++</p> + + <!--========================================================================--> +-<h2><a name="letter+digit-def">char-set:letter+digit</a></h2> ++<h2 id="letter+digit-def">char-set:letter+digit</h2> + <p> + The union of <code>char-set:letter</code> and <code>char-set:digit.</code> +- ++</p> + <!--========================================================================--> +-<h2><a name="graphic-def">char-set:graphic</a></h2> ++<h2 id="graphic-def">char-set:graphic</h2> + <p> + A graphic character is one that would put ink on paper. The ASCII and Latin-1 + graphic characters are the members of +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td><code>char-set:letter</code></td></tr> + <tr><td><code>char-set:digit</code></td></tr> + <tr><td><code>char-set:punctuation</code></td></tr> +@@ -1575,30 +1745,38 @@ graphic characters are the members of + </div> + + <!--========================================================================--> +-<h2><a name="printing-def">char-set:printing</a></h2> ++<h2 id="printing-def">char-set:printing</h2> + <p> + A printing character is one that would occupy space when printed, <em>i.e.</em>, + a graphic character or a space character. <code>char-set:printing</code> is the union + of <code>char-set:whitespace</code> and <code>char-set:graphic.</code> +- ++</p> + <!--========================================================================--> +-<h2><a name="whitespace-def">char-set:whitespace</a></h2> ++<h2 id="whitespace-def">char-set:whitespace</h2> + <p> + In Unicode, a whitespace character is either ++</p> + <ul> + <li> a character with one of the space, line, or paragraph separator categories + (Zs, Zl or Zp) of the Unicode character database. ++ </li> + <li> U+0009 Horizontal tabulation (\t control-I) ++ </li> + <li> U+000A Line feed (\n control-J) ++ </li> + <li> U+000B Vertical tabulation (\v control-K) ++ </li> + <li> U+000C Form feed (\f control-L) ++ </li> + <li> U+000D Carriage return (\r control-M) ++ </li> + </ul> + + <p> + There are 24 whitespace characters in Unicode 3.0: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>0009</td> <td>HORIZONTAL TABULATION </td> <td> \t control-I</td></tr> + <tr><td>000A</td> <td>LINE FEED </td> <td> \n control-J</td></tr> + <tr><td>000B</td> <td>VERTICAL TABULATION </td> <td> \v control-K</td></tr> +@@ -1630,11 +1808,12 @@ The ASCII whitespace characters are the first six characters in the above list + -- line feed, horizontal tabulation, vertical tabulation, form feed, carriage + return, and space. These are also exactly the characters recognised by the + Posix <code>isspace()</code> procedure. Latin-1 adds the no-break space. +- ++</p> + <p> + Note: Java's <code>isWhitespace()</code> method is incompatible, including +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>0009</td> <td>HORIZONTAL TABULATION </td> <td> (\t control-I)</td></tr> + <tr><td>001C</td> <td>FILE SEPARATOR </td> <td> (control-\)</td></tr> + <tr><td>001D</td> <td>GROUP SEPARATOR </td> <td>(control-])</td></tr> +@@ -1642,10 +1821,11 @@ Note: Java's <code>isWhitespace()</code> method is incompatible, including + <tr><td>001F</td> <td>UNIT SEPARATOR </td> <td>(control-_)</td></tr> + </table> + </div> +-<p class=continue> ++<p class="continue"> + and excluding +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00A0</td> <td>NO-BREAK SPACE</td></tr> + </table> + </div> +@@ -1654,67 +1834,71 @@ Java's excluding the no-break space means that tokenizers can simply break + character streams at "whitespace" boundaries. However, the exclusion introduces + exceptions in other places, <em>e.g.</em> <code>char-set:printing</code> is no longer simply the + union of <code>char-set:graphic</code> and <code>char-set:whitespace.</code> +- ++</p> + + <!--========================================================================--> +-<h2><a name="iso-control-def">char-set:iso-control</a></h2> ++<h2 id="iso-control-def">char-set:iso-control</h2> + <p> + The ISO control characters are the Unicode/Latin-1 characters in the ranges + [U+0000,U+001F] and [U+007F,U+009F]. +- ++</p> + <p> + ASCII restricts this set to the characters in the range [U+0000,U+001F] + plus the character U+007F. +- ++</p> + <p> + Note that Unicode defines other control characters which do not belong to this + set (hence the qualifying prefix "iso-" in the name). This restriction is + compatible with the Java <code>IsISOControl()</code> method. +- ++</p> + + <!--========================================================================--> +-<h2><a name="punctuation-def">char-set:punctuation</a></h2> ++<h2 id="punctuation-def">char-set:punctuation</h2> + <p> + In Unicode, a punctuation character is any character that has one of the + punctuation categories in the Unicode character database (Pc, Pd, Ps, + Pe, Pi, Pf, or Po.) +- ++</p> + <p> + ASCII has 23 punctuation characters: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + !"#%&'()*,-./:;?@[\]_{} + </pre> + <p> + Latin-1 adds six more: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00A1 </td> <td> INVERTED EXCLAMATION MARK +-<tr><td>00AB </td> <td> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +-<tr><td>00AD </td> <td> SOFT HYPHEN +-<tr><td>00B7 </td> <td> MIDDLE DOT +-<tr><td>00BB </td> <td> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +-<tr><td>00BF </td> <td> INVERTED QUESTION MARK +-</table> ++</td></tr><tr><td>00AB </td> <td> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK ++</td></tr><tr><td>00AD </td> <td> SOFT HYPHEN ++</td></tr><tr><td>00B7 </td> <td> MIDDLE DOT ++</td></tr><tr><td>00BB </td> <td> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK ++</td></tr><tr><td>00BF </td> <td> INVERTED QUESTION MARK ++</td></tr></table> + </div> + + <p> +-Note that the nine ASCII characters <code>$+<=>^`|~</code> are <em>not</em> ++Note that the nine ASCII characters <code>$+<=>^`|~</code> are <em>not</em> + punctuation. They are "symbols." +- ++</p> + + <!--========================================================================--> +-<h2><a name="symbol-def">char-set:symbol</a></h2> ++<h2 id="symbol-def">char-set:symbol</h2> + <p> + In Unicode, a symbol is any character that has one of the symbol categories + in the Unicode character database (Sm, Sc, Sk, or So). There + are nine ASCII symbol characters: +-<pre class=code-example> ++</p> ++<pre class="code-example"> + $+<=>^`|~ + </pre> + <p> + Latin-1 adds 18 more: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>00A2 </td> <td> CENT SIGN </td></tr> + <tr><td>00A3 </td> <td> POUND SIGN </td></tr> + <tr><td>00A4 </td> <td> CURRENCY SIGN </td></tr> +@@ -1737,20 +1921,24 @@ Latin-1 adds 18 more: + </div> + + <!--========================================================================--> +-<h2><a name="blank-def">char-set:blank</a></h2> ++<h2 id="blank-def">char-set:blank</h2> + + <p> + Blank chars are horizontal whitespace. In Unicode, a blank character is either ++</p> + <ul> + <li> a character with the space separator category (Zs) in the Unicode + character database. ++ </li> + <li> U+0009 Horizontal tabulation (\t control-I) ++ </li> + </ul> + + <p> + There are eighteen blank characters in Unicode 3.0: +-<div class=inset> +-<table cellspacing=0 cellpadding=0> ++</p> ++<div class="inset"> ++<table cellpadding="0" cellspacing="0"> + <tr><td>0009 </td> <td> HORIZONTAL TABULATION </td> <td> \t control-I </td></tr> + <tr><td>0020 </td> <td> SPACE </td> <td> Zs </td></tr> + <tr><td>00A0 </td> <td> NO-BREAK SPACE </td> <td> Zs </td></tr> +@@ -1774,21 +1962,22 @@ There are eighteen blank characters in Unicode 3.0: + <p> + The ASCII blank characters are the first two characters above -- + horizontal tab and space. Latin-1 adds the no-break space. +- ++</p> + <p> + Java doesn't have the concept of "blank" characters, so there are no + compatibility issues. +- ++</p> + + <!--========================================================================--> +-<h1><a name="ReferenceImp">Reference implementation</a></h1> ++<h2 id="ReferenceImp">Reference implementation</h2> + <p> + This SRFI comes with a reference implementation. It resides at: +-<div class=inset> +- <a href="http://srfi.schemers.org/srfi-14/srfi-14.scm"> +-http://srfi.schemers.org/srfi-14/srfi-14.scm</a> ++</p> ++<div class="inset"> ++ <a href="https://srfi.schemers.org/srfi-14/srfi-14.scm"> ++https://srfi.schemers.org/srfi-14/srfi-14.scm</a> + </div> +-<p class=continue> ++<p class="continue"> + I have placed this source on the Net with an unencumbered, "open" copyright. + Some of the code in the reference implementation bears a distant family + relation to the MIT Scheme implementation, and being derived from that code, +@@ -1797,37 +1986,45 @@ open-source copyright -- see the source file for details). The remainder of + the code was written by myself for scsh or for this SRFI; I have placed this + code under the scsh copyright, which is also a generic BSD-style open-source + copyright. +- ++</p> + <p> + The code is written for portability and should be simple to port to + any Scheme. It has only the following deviations from R4RS, clearly + discussed in the comments: ++</p> + <ul> + <li> an <code>error</code> procedure; ++ </li> + <li> the R5RS <code>values</code> procedure for producing multiple return values; ++ </li> + <li> a simple <code>check-arg</code> procedure for argument checking; ++ </li> + <li> <code>let-optionals*</code> and <code>:optional</code> macros for for parsing, checking and defaulting + optional arguments from rest lists; ++ </li> + <li> The SRFI-19 <code>define-record-type</code> form; ++ </li> + <li> <code>bitwise-and</code> for the hash function; +- <li> <code>%latin1->char</code> and <code>%char->latin1</code>. ++ </li> ++ <li> <code>%latin1->char</code> and <code>%char->latin1</code>. ++ </li> + </ul> + + <p> + The library is written for clarity and well-commented; the current source is + about 375 lines of source code and 375 lines of comments and white space. + It is also written for efficiency. Fast paths are provided for common cases. +- ++</p> + <p> + This is not to say that the implementation can't be tuned up for + a specific Scheme implementation. There are notes in comments addressing + ways implementors can tune the reference implementation for performance. +- ++</p> + <p> + In short, I've written the reference implementation to make it as painless + as possible for an implementor -- or a regular programmer -- to adopt this + library and get good results with it. +- ++</p> + <p> + The code uses a rather simple-minded, inefficient representation for + ASCII/Latin-1 char-sets -- a 256-character string. The character whose code is +@@ -1836,15 +2033,15 @@ not in the set if <var>s[i]</var> = ASCII 0 (nul). + A much faster and denser representation would be 16 or 32 bytes worth + of bit string. A portable implementation using bit sets awaits standards for + bitwise logical-ops and byte vectors. +- ++</p> + <p> + "Large" character types, such as Unicode, should use a sparse representation, + taking care that the Latin-1 subset continues to be represented with a + dense 32-byte bit set. +- ++</p> + + <!--========================================================================--> +-<h1><a name="Acknowledgements">Acknowledgements</a></h1> ++<h2 id="Acknowledgements">Acknowledgements</h2> + <p> + The design of this library benefited greatly from the feedback provided during + the SRFI discussion phase. Among those contributing thoughtful commentary and +@@ -1857,114 +2054,127 @@ Kiselyov, Bengt Kleberg, Donovan Kolbly, Bruce Korb, Shriram Krishnamurthi, + Bruce Lewis, Tom Lord, Brad Lucier, Dave Mason, David Rush, Klaus Schilling, + Jonathan Sobel, Mike Sperber, Mikael Staldal, Vladimir Tsyshevsky, Donald + Welsh, and Mike Wilson. I am grateful to them for their assistance. +- ++</p> + <p> + I am also grateful the authors, implementors and documentors of all the + systems mentioned in the introduction. Aubrey Jaffer should be noted for his + work in producing Web-accessible versions of the R5RS spec, which was a + tremendous aid. +- ++</p> + <p> + This is not to imply that these individuals necessarily endorse the final + results, of course. +- ++</p> + <p> + During this document's long development period, great patience was exhibited + by Mike Sperber, who is the editor for the SRFI, and by Hillary Sullivan, + who is not. +- ++</p> + <!--========================================================================--> +-<h1><a name="Links">References & links</a></h1> ++<h2 id="Links">References & links</h2> + + <dl> +-<dt class=biblio><strong><a name="Java">[Java]</a></strong> ++<dt class="biblio"><strong><a name="Java">[Java]</a></strong> ++</dt> + <dd> +- The following URLs provide documentation on relevant Java classes. <br> ++ The following URLs provide documentation on relevant Java classes. <br /> + + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Character.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/StringBuffer.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/StringBuffer.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collator.html">http://java.sun.com/products/jdk/1.2/docs/api/java/text/Collator.html</a> +- <br> ++ <br /> + <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/text/package-summary.html">http://java.sun.com/products/jdk/1.2/docs/api/java/text/package-summary.html</a> + +-<dt class=biblio><strong><a name="MIT-Scheme">[MIT-Scheme]</a></strong> ++</dd> ++<dt class="biblio"><strong><a name="MIT-Scheme">[MIT-Scheme]</a></strong> ++</dt> + <dd> + <a href="http://www.swiss.ai.mit.edu/projects/scheme/">http://www.swiss.ai.mit.edu/projects/scheme/</a> + +-<dt class=biblio><strong><a name="R5RS">[R5RS]</a></strong></dt> +-<dd>Revised<sup>5</sup> report on the algorithmic language Scheme.<br> +- R. Kelsey, W. Clinger, J. Rees (editors). <br> +- Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br> +- and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br> ++</dd> ++<dt class="biblio"><strong><a name="R5RS">[R5RS]</a></strong></dt> ++<dd>Revised<sup>5</sup> report on the algorithmic language Scheme.<br /> ++ R. Kelsey, W. Clinger, J. Rees (editors). <br /> ++ Higher-Order and Symbolic Computation, Vol. 11, No. 1, September, 1998. <br /> ++ and ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998. <br /> + Available at <a href="http://www.schemers.org/Documents/Standards/"> + http://www.schemers.org/Documents/Standards/</a>. + +-<dt class=biblio><strong>[SRFI]</strong></dt> ++</dd> ++<dt class="biblio"><strong>[SRFI]</strong></dt> + <dd> +- The SRFI web site. <br> +- <a href="http://srfi.schemers.org/">http://srfi.schemers.org/</a> ++ The SRFI web site. <br /> ++ <a href="https://srfi.schemers.org/">http://srfi.schemers.org/</a> + +-<dt class=biblio><strong>[SRFI-14]</strong></dt> ++</dd> ++<dt class="biblio"><strong>[SRFI-14]</strong></dt> + <dd> +- SRFI-14: String libraries. <br> +- <a href="http://srfi.schemers.org/srfi-14/">http://srfi.schemers.org/srfi-14/</a> +- ++ SRFI-14: String libraries. <br /> ++ <a href="">http://srfi.schemers.org/srfi-14/</a> + <dl> + <dt> + This document, in HTML: +- <dd><a href="http://srfi.schemers.org/srfi-14/srfi-14.html"> +- http://srfi.schemers.org/srfi-14/srfi-14.html</a> +- ++ </dt> ++ <dd><a href=""> ++ https://srfi.schemers.org/srfi-14/srfi-14.html</a> ++ </dd> + <dt> + This document, in plain text format: +- <dd><a href="http://srfi.schemers.org/srfi-14/srfi-14.txt"> +- http://srfi.schemers.org/srfi-14/srfi-14.txt</a> +- ++ </dt> ++ <dd><a href="https://srfi.schemers.org/srfi-14/srfi-14.txt"> ++ https://srfi.schemers.org/srfi-14/srfi-14.txt</a> ++ </dd> + <dt> Source code for the reference implementation: ++ </dt> + <dd> +- <a href="http://srfi.schemers.org/srfi-14/srfi-14.scm"> +- http://srfi.schemers.org/srfi-14/srfi-14.scm</a> +- ++ <a href="https://srfi.schemers.org/srfi-14/srfi-14.scm"> ++ https://srfi.schemers.org/srfi-14/srfi-14.scm</a> ++ </dd> + <dt> Scheme 48 module specification, with typings: ++ </dt> + <dd> +- <a href="http://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm"> +- http://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm</a> +- ++ <a href="https://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm"> ++ https://srfi.schemers.org/srfi-14/srfi-14-s48-module.scm</a> ++ </dd> + <dt> Regression-test suite: +- <dd> <a href="http://srfi.schemers.org/srfi-14/srfi-14-tests.scm"> +- http://srfi.schemers.org/srfi-14/srfi-14-tests.scm</a> +- ++ </dt> ++ <dd> <a href="https://srfi.schemers.org/srfi-14/srfi-14-tests.scm"> ++ https://srfi.schemers.org/srfi-14/srfi-14-tests.scm</a> ++ </dd> + </dl> + </dd> + +-<dt class=biblio><strong><a name="Unicode">[Unicode]</a></strong> ++<dt class="biblio"><strong><a name="Unicode">[Unicode]</a></strong> ++</dt> + <dd> + <a href="http://www.unicode.org/">http://www.unicode.org/</a> +- +-<dt class=biblio><strong><a name="UnicodeData">[UnicodeData]</a></strong> ++</dd> ++<dt class="biblio"><strong><a name="UnicodeData">[UnicodeData]</a></strong> ++</dt> + <dd> +- The Unicode character database. <br> ++ The Unicode character database. <br /> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt</a> +- <br> ++ <br /> + <a href="ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html">ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.html</a> ++</dd> + </dl> + + <!--========================================================================--> +-<h1><a name="Copyright">Copyright</a></h1> ++<h2 id="copyright">Copyright</h2> + + <p> + Certain portions of this document -- the specific, marked segments of text + describing the <abbr title="Revised^5 Report on Scheme"><a href="#R5RS">R5RS</a></abbr> procedures -- were adapted with permission from the R5RS + report. +- ++</p> + <p> + All other text is copyright (C) Olin Shivers (1998, 1999, 2000). + All Rights Reserved. +- ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -1987,10 +2197,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> +- ++ <hr /> ++ <address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Michael Sperber</a></address> + </body> +-</html> +-<!-- ++</html><!-- + LocalWords: SRFI refs HTML css hackery sans Netscape td pre div para + LocalWords: proc def procs defi's defn dl dt defi dd NS RS rs procx + LocalWords: stylesheet IE biblio IE's Internationalisation ascii doc +@@ -2021,3 +2231,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + LocalWords: tokenizers iso Pd Ps Pe Pf AB BB BF Sm Sc Sk AF MACRON + LocalWords: PILCROW soh nul ops Shiro Kawai subform + --> ++ +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html +index a335320..81f4963 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-16.html +@@ -1,57 +1,78 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-16 ┃ ++┃ Commit: bc4412a02f5e7b6f9605365fcccda2866781be85 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 16: Syntax for procedures of variable arity</title> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 16: Syntax for procedures of variable arity.</h1> + +-SRFI 16: Syntax for procedures of variable arity. ++<p>by Lars T Hansen</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 16 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-16/srfi-16.html">https://srfi.schemers.org/srfi-16/srfi-16.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2 id="status">Status</h2> + +-Lars T Hansen +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-16/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/11/01 +-<LI>Draft: 1999/11/06-2000/01/07 +-<LI>Final: 2000/03/10 +-</UL> +- +-<H1>Abstract</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+16+at+srfi+dotschemers+dot+org">srfi-16@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-16">archive</a>.</p> ++<ul> ++ <li>Received: 1999-11-01</li> ++ <li>Draft: 1999-11-06--2000-01-07</li> ++ <li>Final: 2000-03-10</li> ++</ul> + ++<h2>Abstract</h2> ++<p> + CASE-LAMBDA, a syntax for procedures with a variable number of arguments, + is introduced. ++</p> + +-<H1>Rationale</H1> +- ++<h2>Rationale</h2> ++<p> + CASE-LAMBDA reduces the clutter of procedures that execute different + code depending on the number of arguments they were passed; it is + a pattern-matching mechanism that matches on the number of arguments. + CASE-LAMBDA is available in some Scheme systems. +- ++</p> + <p>While CASE-LAMBDA can be implemented as a macro using only facilities + available in R5RS Scheme, it admits considerable implementation-specific + optimization. ++</p> + +- +-<H1>Specification</H1> ++<h2>Specification</h2> + + <dl> +-<dt><a name="case-lambda"></a> ++<dt id="case-lambda"> + (CASE-LAMBDA <clause> ...) +-<br> Syntax ++<br /> Syntax ++</dt> + <dd> +-<p>Each <clause> should have the form (<formals> <body>), where ++<p>Each <clause> should have the form (<formals> <body>), where + <formals> is a formal arguments list as for LAMBDA, cf section + 4.1.4 of the R5RS. Each <body> is a <tail-body>, cf section + 3.5 of the R5RS. +- ++</p> + <p>A CASE-LAMBDA expression evaluates to a procedure that accepts + a variable number of arguments and is lexically scoped in the + same manner as procedures resulting from LAMBDA expressions. +@@ -63,10 +84,10 @@ optimization. + locations, the <body> is evaluated in the extended environment, + and the results of <body> are returned as the results of the + procedure call. +- ++</p> + <p>It is an error for the arguments not to agree with the <formals> + of any <clause>. +- ++</p> + <pre> + (define plus + (case-lambda +@@ -85,23 +106,26 @@ optimization. + ((a b) (* a b))) + 1 2 3) --> error + </pre> ++</dd> + </dl> + +-<H1>Implementation</H1> +- ++<h2>Implementation</h2> ++<p> + The following implementation is written in R5RS Scheme. It is not + compatible with the IEEE Scheme standard because the IEEE standard does + not contain the high-level macro system. +- ++</p> + <p>The implementation assumes that some top-level names defined by the + R5RS are bound to their original values. +- +-<p> ++</p> + <pre> + ;; This code is in the public domain. + + (define-syntax case-lambda + (syntax-rules () ++ ((case-lambda) ++ (lambda args ++ (error "CASE-LAMBDA without any clauses."))) + ((case-lambda + (?a1 ?e1 ...) + ?clause1 ...) +@@ -135,15 +159,14 @@ R5RS are bound to their original values. + ?clause1 ...)) + ((case-lambda "IMPROPER" ?args ?l ?k ?al (?ar ?e1 ...) + ?clause1 ...) +- (if (>= ?l ?k) ++ (if (>= ?l ?k) + (apply (lambda ?al ?e1 ...) ?args) + (case-lambda "CLAUSE" ?args ?l + ?clause1 ...))))) + </pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Lars T Hansen (1999). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -167,11 +190,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Mon Apr 19 20:38:48 CEST 2004 ++Last modified: Fri Sep 18 18:34:31 MST 2009 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html +index dc06d9d..e21b0b6 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-17.html +@@ -1,41 +1,63 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-17 ┃ ++┃ Commit: e71ee349666a7ea57f44e70115f019d6074090fb ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 17: Generalized set!</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> +- +-SRFI 17: Generalized <code>set!</code> +- +-<H1>Author</H1> ++<h1>SRFI 17: Generalized <code>set!</code></h1> + +-Per Bothner ++<p>by Per Bothner</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 17 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-17/srfi-17.html">https://srfi.schemers.org/srfi-17/srfi-17.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Status</H1> ++<h2>Status</h2> + +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-17/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/12/08 +-<LI>Draft: 2000/01/16-2000/03/17 +-<LI>Revised: 2000/04/28 +-<LI>Final: 2000/07/24 +-</UL> +- +-<H1>Abstract</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+17+at+srfi+dotschemers+dot+org">srfi-17@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-17">archive</a>.</p> ++<ul> ++ <li>Received: 1999-12-08</li> ++ <li>Draft: 2000-01-16--2000-03-17</li> ++ <li>Revised: 2000-04-28</li> ++ <li>Final: 2000-07-24</li> ++</ul> + ++<h2>Abstract</h2> ++<p> + This is a proposal to allow procedure calls that evaluate + to the "value of a location" to be used to <em>set</em> + the value of the location, when used as the first + operand of <code>set!</code>. + For example: ++</p> + <pre> + (set! (car x) (car y)) + </pre> ++<p> + becomes equivalent to ++</p> + <pre> + (set-car! x (car y)) + </pre> +@@ -49,14 +71,16 @@ which can be used in <code>setf</code> and some other special forms. + However, the Common Lisp concept is based on the idea of + compile-time recognition of special "location-producing" functions; + this does not seem to be in the "spirit of Scheme". ++</p> + <p> + This SRFI proposes an extension of <code>set!</code> + so that it provides similar functionality as Common Lisp's <code>setf</code>, + except that the updater is associated with a procedure value, + rather than a name. ++</p> + +-<H1>Rationale</H1> +- ++<h2>Rationale</h2> ++<p> + There is ample precedent for general "lvalues" on the + left-hand side of an assignment. This includes most statically + typed languages, and many dynamically typed languages (including APL +@@ -66,6 +90,7 @@ Another is that it becomes visually clearer which expression is the new value, + and which are parameters. Also, the visual consistency between + an expression evaluated for its value and one evaluated to yield + a location seems natural to people. ++</p> + <p> + For most languages, the set of lvalue-producing operators is limited + (typically array indexing and field selection). Some languages have +@@ -77,19 +102,21 @@ mutable variables are first-class "cells", and accessing the + contents of a cell requires an explicit operator. This is also not + compatible with Scheme. Instead we need to stick to the model + where using a variable in most contexts means using its value, +-but referring to a variable in certain lvalue contexts (lhs of ++but refering to a variable in certain lvalue contexts (lhs of + assignment) refers to its actual location. Sticking to this model + for general "lvalue expressions" in <code>set!</code> means + that "evaluation" must be done differently from normal + evaluation when in an "lvalue context". That is what this proposal does. ++</p> + <p> + This is a controversial issue. This srfi does not wish to imply that + all Scheme implementations should support this feature; it only + requests that implementations that <em>do</em> implement + generalized <code>set!</code> should be compatible with this srfi. ++</p> + +-<H1><a name="!set">Specification</a></H1> +- ++<h2 id="!set">Specification</h2> ++<p> + The special form <code>set!</code> is extended so the first operand + can be a procedure application, and not just a variable. + The procedure is typically one that extracts a component from +@@ -97,10 +124,13 @@ some data structure. Informally, when the procedure is called + in the first operand of <code>set!</code>, it causes the corresponding + component to be <em>replaced</em> by the second operand. + For example, ++</p> + <pre> + (set (vector-ref x i) v) + </pre> ++<p> + would be equivalent to: ++</p> + <pre> + (vector-set! x i v) + </pre> +@@ -109,12 +139,16 @@ Each procedure that may be used as the first operand to <code>set!</code> + must have a corresponding "setter" procedure. + The builtin procedure <code>setter</code> takes a procedure and returns the + corresponding setter procedure. ++</p> + <p> + We define: ++</p> + <pre> + (set! (proc arg ...) value) + </pre> ++<p> + as: ++</p> + <pre> + ((setter proc) arg ... value) + </pre> +@@ -124,9 +158,11 @@ the existing Scheme convention for setter procedures, where + the new value is given last. For example we can define + <code>(setter car)</code> to be <code>set-car!</code>. + An alternative definition would be: ++</p> + <pre> + ((setter proc) value arg ...) ;; Not the actual definition. + </pre> ++<p> + This definition would work better when you consider + procedures that take a variable number of arguments. + This is because it is straight-forward to add one extra +@@ -135,10 +171,12 @@ argument to the end of an argument list that has + a "rest" parameter, then things get more messy. + However, consistency with the existing new-value-last convention + seems more valuable. ++</p> + +-<h2>Standard setters</h2> +- ++<h3>Standard setters</h3> ++<p> + The following standard procedures have pre-defined setters: ++</p> + <pre> + (set! (car x) v) == (set-car! x v) + (set! (cdr x) v) == (set-cdr! x v) +@@ -161,20 +199,23 @@ One useful addition: + variable-length mutable strings.) + --> + +-<h2>Setting setters; properties</h2> +- ++<h3>Setting setters; properties</h3> ++<p> + A setter procedure is a special case of the concept of procedures having + associated <dfn>properties</dfn>. Other properties might include + the procedures's name or usage documentation. + As a <em>hypothetical</em> example (i.e. not part of this SRFI), + we can use the Common Lisp <code>documentation</code> function, + where for example: ++</p> + <pre> + (documentation sqrt) + </pre> ++<p> + returns the "documentation string" (if defined) for <code>sqrt</code>. + Such properties should also be settable using generalized <code>set!</code>. + For example: ++</p> + <pre> + (set! (documentation sqrt) "Calculates the square root.") + </pre> +@@ -184,19 +225,24 @@ This SRFI does + not propose a general "procedure properties" feature, but it + should be compatible with it. It does specify the special case + for the <code>setter</code> property. This is defined such that: ++</p> + <pre> + (set! (setter <var>proc</var>) <var>setter</var>) + </pre> ++<p> + sets the setter procedure associated with <var>proc</var> + to <var>setter</var>. + For example, we can assume ++</p> + <pre> + (set! (setter car) set-car!) + </pre> ++<p> + has been executed by the Scheme prologue. ++</p> + +-<h2>Efficiency Issues</h2> +- ++<h3>Efficiency Issues</h3> ++<p> + If <code>(set! (foo ..) ...)</code> is to be the preferred idiom, + we want to make <code>((setter foo) ...)</code> as efficient + as <code>(set-foo! ...)</code>. +@@ -216,32 +262,42 @@ compilation more difficult. However, the next section does define + a way to inherently tie a setter to a procedure, which does reduce + the problem of inlining generalized <code>set!</code> to the + standard inlining problem. ++</p> + +-<h2><code>getter-with-setter</code></h2> ++<h3 id="getter-with-setter"><code>getter-with-setter</code></h3> + <p>The function <code>getter-with-setter</code> can be used + to define a procedure with associated properties. +-Specifically: <a name="getter-with-setter"></a> ++Specifically: ++</p> + <pre> + (getter-with-setter <var>getter</var> <var>setter</var>) + </pre> ++<p> + This evaluates to a new anonymous procedure which when + applied invokes <var>getter</var>, and whose setter is <var>setter</var>. + It is an error for a program to subsequently try to modify + the setter of the resulting compound. ++</p> + <p> + For example, we could define: ++</p> + <pre> + (define car (getter-with-setter %primitive-car %primitive-set-car!)) + (define set-car! %primitive-set-car!) + </pre> ++<p> + The advantage of this approach that whenever a compiler can inline + <code>car</code>, it can also inline <code>(setter car)</code>. ++</p> + +-<H1>Implementation</H1> +- +-<a href="http://srfi.schemers.org/srfi-17/srfi-17-twobit.scm">Here</a> is a sample implementation ++<h2>Implementation</h2> ++<p> ++<a href="https://srfi.schemers.org/srfi-17/srfi-17-twobit.scm">Here</a> is a sample implementation + for Twobit. +-<p>Here is a sample definition of <code>getter-with-setter</code>: ++</p> ++<p> ++Here is a sample definition of <code>getter-with-setter</code>: ++</p> + <pre> + (define (getter-with-setter get set) + (let ((proc (lambda args (apply get args)))) +@@ -249,9 +305,8 @@ for Twobit. + proc)) + </pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Per Bothner (1999, 2000). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -275,11 +330,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Wed Nov 10 03:14:43 PST 1999 --> + <!-- hhmts start --> +-Last modified: Mon Jul 24 12:00:06 MST 2000 ++Last modified: Fri Sep 18 17:00:11 MST 2009 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html +index b2a612e..c7acadd 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-19.html +@@ -1,13 +1,32 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-19 ┃ ++┃ Commit: 0e90ac1a1a66c4ac3219dd0872fbf62018a94e10 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 19: Time Data Types and Procedures</title> +- <meta name="keywords" content="Scheme, programming language, time +- processing, date processing, Julian Day, SRFI, overdone temporal smut"> +- <link rev=made href="mailto:will.fitzgerald@pobox.com"> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ <meta content="Scheme, programming language, time processing, date processing, Julian Day, SRFI, overdone temporal smut" name="keywords" /> + <!-- This style sheet is from the SRFI-1 description (Olin Shivers), but modified to taste. + --> + <style type="text/css"> ++ /*<![CDATA[*/ + /* A little general layout hackery for headers & the title. */ + body { margin-left: +7%; + font-family: "Georgia", "Times Roman", serif; +@@ -17,8 +36,8 @@ + + code, pre { font-family: "courier new", "courier"; } + +- h1 { margin-left: -5%; } +- h1, h2 { clear: both; } ++ h2 { margin-left: -5%; } ++ h2, h3 { clear: both; } + h1, h2, h3, h4, h5, h6 { color: black } + div.title-text { font-size: large; font-weight: bold; } + +@@ -27,7 +46,7 @@ + + /* This stuff is for definition lists of defined procedures. + ** A proc-def2 is used when you want a stack of procs to go +- ** with one <dd> ... </dd> body. In this case, make the first ++ ** with one <dd> ... < / dd> body. In this case, make the first + ** proc a proc-def1, following ones proc-defi's, and the last one + ** a proc-defn. + ** +@@ -88,9 +107,10 @@ + ** development process and kill them when the document's done. + */ + a.draft { color: red; } ++ /*]]>*/ + </style> +- +- <style type="text/css"; media=all> ++ <style media="all" type="text/css"> ++ /*<![CDATA[*/ + /* Nastiness: Here, I'm using a bug to work around a bug. + ** Netscape rendering bugs mean you need bogus <dt> and <dd> + ** margin settings -- settings which screw up IE's proper rendering. +@@ -117,40 +137,37 @@ + /* Spread out bibliographic lists. */ + dt.biblio { margin-top: 3ex; margin-bottom: 0ex; } + dd.biblio { margin-bottom: 1ex; } ++ /*]]>*/ + </style> + </head> + + <body> + +-<H1>Title</H1> +- +-SRFI 19: Time Data Types and Procedures +- +-<H1>Author</H1> +- +-Will Fitzgerald +- +-<H1>Status</H1> ++<h1>SRFI 19: Time Data Types and Procedures</h1> + +-<p>This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. You can +-access the discussion via <a +-href="http://srfi.schemers.org/srfi-19/mail-archive/maillist.html"> +-the archive of the mailing list</a>. ++<p>by Will Fitzgerald</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 19 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-19/srfi-19.html">https://srfi.schemers.org/srfi-19/srfi-19.html</a>.</p></blockquote></blockquote></blockquote> + ++<h2>Status</h2> + +-<UL> +-<LI>Draft: 2000-02-28 to 2000-08-28 </LI> +-<LI>Final: 2000-08-31</LI> +-<LI>Fixed reference implementation: 2003-02-28</LI> +-<LI>Documentation bug for <code>~D</code> fixed: 2003-05-30</LI> +-<LI>Various Documentation bugs fixed: 2004-03-15</LI> +-</UL> +- +-<H1>Abstract</H1> +- +-Points in time are represented a the number of seconds (with ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+19+at+srfi+dotschemers+dot+org">srfi-19@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-19">archive</a>.</p> ++<ul> ++<li>Draft: 2000-02-28 to 2000-08-28 </li> ++<li>Final: 2000-08-31</li> ++<li>Revised to fix errata: ++ <ul> ++ <li>2003-02-28 (Fixed reference implementation.)</li> ++ <li>2003-05-30 (Fixed documentation bug for <code>~D</code>.)</li> ++ <li>2004-03-15 (Fixed various documentation bugs.)</li> ++ <li>2017-05-05 (Fixed definition of Julian Day and Modified Julian Day.)</li> ++ <li>2019-6-11 (Fixed week number definitions in Table 1. Note that this was an incompatible change to the API.)</li></ul></li></ul> ++ ++<h2>Abstract</h2> ++<p> ++Points in time are represented as the number of seconds (with + nanosecond precision) since "the epoch," a zero point in time. Several + standard variants are defined, including UTC (universal coordinated + time), TAI (international atomic time), and monotonic time. A point in time can also be +@@ -160,45 +177,49 @@ routines are provided. The procedure CURRENT-TIME queries the current + time in a specified variant, with a system-dependent + resolution. Procedures for time arithmetic and time comparisons are + also provided. +- +-<p>A date is a representation of a point in time in the Gregorian ++</p> ++<p> ++A date is a representation of a point in time in the Gregorian + calendar, a 24 hour clock (with nanosecond precision) and a + time zone offset from UTC. Procedures for + converting between time and dates are provided, as well as for reading + and writing string representations of dates. ++</p> + +-<H1>Issues</H1>[None currently] +- ++<h2>Issues</h2> ++<p>[None currently]</p> + +-<H1>Rationale</H1> + ++<h2>Rationale</h2> ++<p> + R5RS Scheme does not provide standard data types for time. This + SRFI addresses this lack by specifying data types for time and + associated procedures. ++</p> + +- +-<H1>Specification</H1> ++<h2>Specification</h2> + + <p>A <b>Time</b> object, which is distinct from all existing types, + defines a point in time or a time duration in some standard time +-system. The standard <a name="#timesystem">time systems</a> are: +- ++system. The standard <span id="timesystem">time systems</span> are: ++</p> + <ul> + <li>Universal Coordinated Time (UTC), +- <li>International Atomic Time (TAI), +- <li>monotonic time (a monotonically increasing point in time from some ++ </li><li>International Atomic Time (TAI), ++ </li><li>monotonic time (a monotonically increasing point in time from some + epoch, which is implementation-dependent), +- <li>CPU time in current thread (implementation dependent), +- <li>CPU time in current process (implementation dependent), +- <li>Time duration. +-</ul> +- ++ </li><li>CPU time in current thread (implementation dependent), ++ </li><li>CPU time in current process (implementation dependent), ++ </li><li>Time duration. ++</li></ul> ++<p> + Implementations are required to implement UTC, monotonic time, CPU + time in current process, and time duration. Implementations are + allowed to create extensions (for example, amount of time spent in + garbage collection). +- +-<p>A <a name="timeobject">time object</a> consists of three components: ++</p> ++<p>A <span id="timeobject">time object</span> consists of three components: ++</p> + <ul> + <li><b>Time type</b>, a symbol representing the time system + representation used. The constants <code>TIME-TAI</code>, +@@ -207,100 +228,110 @@ garbage collection). + <code>TIME-DURATION</code> must be provided for these + symbols. Implementations should provide constants for time type + extensions. +- <li><b>Second</b>, an integer representing the number ++ </li><li><b>Second</b>, an integer representing the number + of whole seconds from "the epoch." +- <li><b>Nanosecond</b>, an ++ </li><li><b>Nanosecond</b>, an + integer of the number of nanoseconds in the fractional + portion. Although a time object has nanosecond precision, clocks + may have a lower resolution. +-</ul> ++</li></ul> + +-<p>A <a name="dateobject"><b>Date</b></a> object, which is distinct from all existing ++<p id="dateobject">A <b>Date</b> object, which is distinct from all existing + types, represents a point in time as represented by the Gregorian + calendar as well as by a time zone. Dates are immutable. A date + consists of the following components: +- ++</p> + <ul> + <li><b>Nanosecond</b>, an integer between 0 and 9,999,999, inclusive. +-<li><b>Second</b>, an integer 0 and 60, inclusive, ++</li> ++<li><b>Second</b>, an integer 0 and 60, inclusive, + (60 represents a leap second) ++</li> + <li><b>Minute</b>, an integer between 0 and 59, inclusive, ++</li> + <li><b>Hour</b>, an integer between 0 and 23, inclusive, ++</li> + <li><b>Day</b>, an integer between 0 and 31, inclusive, the upper limit depending + on the month and year of the point in time, ++</li> + <li><b>Month</b>, an integer between 1 and 12, inclusive; in which 1 means + January, 2 February, and so on. ++</li> + <li><b>Year</b>, an integer representing the year. ++</li> + <li><b>Time zone</b>, an integer representing the number of seconds east of GMT for this timezone. ++</li> + </ul> ++<p> ++A <b>Julian Day</b> represents a point in time as a real number of days ++since -4713-11-24T12:00:00Z (midday UT on 24 November 4714 BC in the ++proleptic Gregorian calendar (1 January 4713 BC in the proleptic Julian calendar)). ++</p> ++<p> ++A <b>Modified Julian Day</b> represents a point in time as a real number of ++days since 1858-11-17T00:00:00Z (midnight UT on 17 November AD 1858). ++</p> + +-<p>A <b>Julian Day</b> represents a point in time as a real number +-of days since -4714-11-24T12:00:00Z (November 24, -4714 at noon, +-UTC). +- +-<p>A <b>Modified Julian Day</b> represents a point in time as a +-real number of days since 1858-11-17T00:00:00Z (November 17, +-1858 at midnight, UTC). +- +-<h2>Constants</h2> +-<P>The following constants are required: +- +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="time-duration">time-duration</a></CODE> +- <DD class=proc-def>Symbol representing Time duration. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic">time-monotonic</a></CODE> +- <DD class=proc-def>Symbol representing monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="time-process">time-process</a></CODE> +- <DD class=proc-def>Symbol representing time spent in current process. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai">time-tai</a></CODE> +- <DD class=proc-def>Symbol representing TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="time-thread">time-thread</a></CODE> +- <DD class=proc-def>Symbol representing time spent in current thread. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc">time-utc</a></CODE> +- <DD class=proc-def>Symbol representting UTC time. +-</DL> +-<h2>Current time and clock resolution</h2> +-<P>The following procedures are required: +- +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="current-date">current-date</a></CODE> [<VAR>tz-offset</VAR>] -> <VAR>date</VAR> +- <DD class=proc-def>Date corresponding to the current UTC time. +- <DT class=proc-def><CODE class=proc-def><a name="current-julian-day">current-julian-day</a></CODE> -> <VAR>jdn</VAR> +- <DD class=proc-def>Current Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="current-modified-julian-day">current-modified-julian-day</a></CODE> -> <VAR>mjdn</VAR> +- <DD class=proc-def>Current Modified Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="current-time">current-time</a></CODE> [<VAR>time-type</VAR>] -> <VAR>time</VAR> +- <DD class=proc-def>Current time, of type <code>time-type</code> system, which defaults to <code>TIME-UTC</code>. +- <DT class=proc-def><CODE class=proc-def><a name="time-resolution">time-resolution</a></CODE> [<VAR>time-type</VAR>] -> <VAR>integer</VAR> +- <DD class=proc-def>Clock resolution, in nanoseconds, of the system clock of type type <code>time-type</code> system, which defaults to <code>TIME-UTC</code>. +-</DL> +-<h2>Time object and accessors</h2> +-<P>The following procedures are required: +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="make-time">make-time</a></CODE> <VAR>type nanosecond second</VAR> -> <VAR>time</VAR> +- <DD class=proc-def>Creates a time object. +- <DT class=proc-def><CODE class=proc-def><a name="time-p">time?</a></CODE> <VAR>object</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if object is a time object, otherwise, <code>#f</code>. +- <DT class=proc-def><CODE class=proc-def><a name="time-type">time-type</a></CODE> <VAR>time</VAR> -> <VAR>time-type</VAR> +- <DD class=proc-def>Time type. +- <DT class=proc-def><CODE class=proc-def><a name="time-nanosecond">time-nanosecond</a></CODE> <VAR>time</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Time nanosecond. +- <DT class=proc-def><CODE class=proc-def><a name="time-second">time-second</a></CODE> <VAR>time</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Time second. +- <DT class=proc-def><CODE class=proc-def><a name="set-time-type!">set-time-type!</a></CODE> <VAR>time time-type</VAR> +- <DD class=proc-def>Changes time type. Note: This changes the semantics of the time object. To convert a time to another ++<h3>Constants</h3> ++<p>The following constants are required: ++</p> ++<dl> ++ <dt class="proc-def" id="time-duration"><code class="proc-def">time-duration</code> ++ </dt><dd class="proc-def">Symbol representing Time duration. ++ </dd><dt class="proc-def" id="time-monotonic"><code class="proc-def">time-monotonic</code> ++ </dt><dd class="proc-def">Symbol representing monotonic time. ++ </dd><dt class="proc-def" id="time-process"><code class="proc-def">time-process</code> ++ </dt><dd class="proc-def">Symbol representing time spent in current process. ++ </dd><dt class="proc-def" id="time-tai"><code class="proc-def">time-tai</code> ++ </dt><dd class="proc-def">Symbol representing TAI time. ++ </dd><dt class="proc-def" id="time-thread"><code class="proc-def">time-thread</code> ++ </dt><dd class="proc-def">Symbol representing time spent in current thread. ++ </dd><dt class="proc-def" id="time-utc"><code class="proc-def">time-utc</code> ++ </dt><dd class="proc-def">Symbol representing UTC time. ++</dd></dl> ++<h3>Current time and clock resolution</h3> ++<p>The following procedures are required: ++</p> ++<dl> ++ <dt class="proc-def" id="current-date"><code class="proc-def">current-date</code> [<var>tz-offset</var>] -> <var>date</var> ++ </dt><dd class="proc-def">Date corresponding to the current UTC time. ++ </dd><dt class="proc-def" id="current-julian-day"><code class="proc-def">current-julian-day</code> -> <var>jdn</var> ++ </dt><dd class="proc-def">Current Julian Day. ++ </dd><dt class="proc-def" id="current-modified-julian-day"><code class="proc-def">current-modified-julian-day</code> -> <var>mjdn</var> ++ </dt><dd class="proc-def">Current Modified Julian Day. ++ </dd><dt class="proc-def" id="current-time"><code class="proc-def">current-time</code> [<var>time-type</var>] -> <var>time</var> ++ </dt><dd class="proc-def">Current time, of type <code>time-type</code> system, which defaults to <code>TIME-UTC</code>. ++ </dd><dt class="proc-def" id="time-resolution"><code class="proc-def">time-resolution</code> [<var>time-type</var>] -> <var>integer</var> ++ </dt><dd class="proc-def">Clock resolution, in nanoseconds, of the system clock of type type <code>time-type</code> system, which defaults to <code>TIME-UTC</code>. ++</dd></dl> ++<h3>Time object and accessors</h3> ++<p>The following procedures are required: ++</p> ++<dl> ++ <dt class="proc-def" id="make-time"><code class="proc-def">make-time</code> <var>type nanosecond second</var> -> <var>time</var> ++ </dt><dd class="proc-def">Creates a time object. ++ </dd><dt class="proc-def" id="time-p"><code class="proc-def">time?</code> <var>object</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if object is a time object, otherwise, <code>#f</code>. ++ </dd><dt class="proc-def" id="time-type"><code class="proc-def">time-type</code> <var>time</var> -> <var>time-type</var> ++ </dt><dd class="proc-def">Time type. ++ </dd><dt class="proc-def" id="time-nanosecond"><code class="proc-def">time-nanosecond</code> <var>time</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Time nanosecond. ++ </dd><dt class="proc-def" id="time-second"><code class="proc-def">time-second</code> <var>time</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Time second. ++ </dd><dt class="proc-def" id="set-time-type!"><code class="proc-def">set-time-type!</code> <var>time time-type</var> ++ </dt><dd class="proc-def">Changes time type. Note: This changes the semantics of the time object. To convert a time to another + system of representation, use one of the conversion procedures. +- <DT class=proc-def><CODE class=proc-def><a name="set-time-nanosecond!">set-time-nanosecond!</a></CODE> <VAR>time integer</VAR> +- <DD class=proc-def>Changes time nanosecond. +- <DT class=proc-def><CODE class=proc-def><a name="set-time-second!">set-time-second!</a></CODE> <VAR>time integer</VAR> +- <DD class=proc-def>Changes time second. +- <DT class=proc-def><CODE class=proc-def><a name="copy-time">copy-time</a></CODE> <VAR>time1</VAR> -> <VAR>time2</VAR> +- <DD class=proc-def>Creates a new time object, with the same time type, nanosecond, and second as <var>time1</var>. +-</DL> ++ </dd><dt class="proc-def" id="set-time-nanosecond!"><code class="proc-def">set-time-nanosecond!</code> <var>time integer</var> ++ </dt><dd class="proc-def">Changes time nanosecond. ++ </dd><dt class="proc-def" id="set-time-second!"><code class="proc-def">set-time-second!</code> <var>time integer</var> ++ </dt><dd class="proc-def">Changes time second. ++ </dd><dt class="proc-def" id="copy-time"><code class="proc-def">copy-time</code> <var>time1</var> -> <var>time2</var> ++ </dt><dd class="proc-def">Creates a new time object, with the same time type, nanosecond, and second as <var>time1</var>. ++</dd></dl> + +-<h2>Time comparison procedures</h2> ++<h3>Time comparison procedures</h3> + +-<P>All of the time comparison procedures require the time objects to ++<p>All of the time comparison procedures require the time objects to + be of the same type. It is an error to use these procedures on time + objects of different types. For the point-in-time measurements (e.g., + <code>TIME-TAI</code> and <code>TIME-UTC</code>), the semantics are +@@ -308,243 +339,259 @@ described in plain text. For durations, (e.g., + <code>TIME-DURATION</code>, <code>TIME-CPU</code>, the semantics are + described in parentheses. + +-<p> The following procedures are required: +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="time<=-p">time<=?</a></CODE> <VAR>time1 time2</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if <var>time1</var> is before or at (less than or equal to) <var>time2</var>, <code>#f</code> otherwise. +- <DT class=proc-def><CODE class=proc-def><a name="time<-p">time<?</a></CODE> <VAR>time1 time2</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if <var>time1</var> is before (less than) <var>time2</var>, <code>#f</code> otherwise. +- <DT class=proc-def><CODE class=proc-def><a name="time=-p">time=?</a></CODE> <VAR>time1 time2</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if <var>time1</var> at (equal) <var>time2</var>, <code>#f</code> otherwise. +- <DT class=proc-def><CODE class=proc-def><a name="time>=-p">time>=?</a></CODE> <VAR>time1 time2</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if <var>time1</var> is at or after (greater than or equal to) <var>time2</var>, <code>#f</code> otherwise. +- <DT class=proc-def><CODE class=proc-def><a name="time>-p">time>?</a></CODE> <VAR>time1 time2</VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if <var>time1</var> is after (greater than) <var>time2</var>, <code>#f</code> otherwise. +-</DL> +- +-<h2>Time arithmetic procedures</h2> +- +-<P>The following procedures are required. +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="time-difference">time-difference</a></CODE> <VAR>time1 time2</VAR> -> <VAR>time-duration</VAR> +- <DD class=proc-def>The <code>TIME-DURATION</code> between <VAR>time1</VAR> and <VAR>time2</VAR>. It is an error if <VAR>time1</VAR> and <VAR>time2</VAR> are of different time types. A new time object is created. +- <DT class=proc-def><CODE class=proc-def><a name="time-difference!">time-difference!</a></CODE> <VAR>time1 time2</VAR> -> <VAR>time-duration</VAR> +- <DD class=proc-def>The <code>TIME-DURATION</code> between <VAR>time1</VAR> and <VAR>time2</VAR>. It is an error if <VAR>time1</VAR> and <VAR>time2</VAR> are of different time types. <var>Time1</var> may be used to create the resulting <code>TIME-DURATION</code> object. +- <DT class=proc-def><CODE class=proc-def><a name="add-duration">add-duration</a></CODE> <VAR>time1 time-duration</VAR> -> <VAR>time</VAR> +- <DD class=proc-def>The time resulting from adding <VAR>time-duration</VAR> to <VAR>time1</VAR>, which is a time object of the same time type as <VAR>time1</VAR>. A new time object is created. +- <DT class=proc-def><CODE class=proc-def><a name="add-duration!">add-duration!</a></CODE> <VAR>time1 time-duration</VAR> -> <VAR>time</VAR> +- <DD class=proc-def>The time resulting from adding <VAR>time-duration</VAR> to <VAR>time1</VAR>, which is a time object of the same time type as <VAR>time1</VAR>. <var>Time1</var> may used to create the resulting time object. +- <DT class=proc-def><CODE class=proc-def><a name="subtract-duration">subtract-duration</a></CODE> <VAR>time1 time-duration</VAR> -> <VAR>time</VAR> +- <DD class=proc-def>The time resulting from subtracting <VAR>time-duration</VAR> to <VAR>time1</VAR>, which is a time object of the same time type as <VAR>time1</VAR>. A new time object is created. +- <DT class=proc-def><CODE class=proc-def><a name="subtract-duration!">subtract-duration!</a></CODE> <VAR>time1 time-duration</VAR> -> <VAR>time</VAR> +- <DD class=proc-def>The time resulting from subtracting <VAR>time-duration</VAR> to <VAR>time1</VAR>, which is a time object of the same time type as <VAR>time1</VAR>. <var>Time1</var> may used to create the resulting time object. +-</DL> +- +-<h2>Date object and accessors</h2> +- +-<P>Date objects are immutable once created. The following procedures are required. +-<DL> +- +- <DT class=proc-def><CODE class=proc-def><a name="make-date">make-date</a></CODE> <VAR>nanosecond second minute hour day month year zone-offset</VAR> -> <VAR>date</VAR> +- <DD class=proc-def>Creates a date object. +- <DT class=proc-def><CODE class=proc-def><a name="date-p">date?</a></CODE> <VAR>date </VAR> -> <VAR>boolean</VAR> +- <DD class=proc-def><code>#t</code> if object is a time object, otherwise, <code>#f</code>. +- <DT class=proc-def><CODE class=proc-def><a name="date-nanosecond">date-nanosecond</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date nanosecond. +- <DT class=proc-def><CODE class=proc-def><a name="date-second">date-second</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date second. +- <DT class=proc-def><CODE class=proc-def><a name="date-minute">date-minute</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date minute. +- <DT class=proc-def><CODE class=proc-def><a name="date-hour">date-hour</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date hour. +- <DT class=proc-def><CODE class=proc-def><a name="date-day">date-day</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date day. +- <DT class=proc-def><CODE class=proc-def><a name="date-month">date-month</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date month. +- <DT class=proc-def><CODE class=proc-def><a name="date-year">date-year</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date year. +- <DT class=proc-def><CODE class=proc-def><a name="date-zone-offset">date-zone-offset</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>Date time zone offset. +- <DT class=proc-def><CODE class=proc-def><a name="date-year-day">date-year-day</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>The ordinal day of the year of this date. January 1 is 1, etc. +- <DT class=proc-def><CODE class=proc-def><a name="date-week-day">date-week-day</a></CODE> <VAR>date</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>The day of the week of this date, where Sunday=0, Monday=1, etc. +- <DT class=proc-def><CODE class=proc-def><a name="date-week-number">date-week-number</a></CODE> <VAR>date day-of-week-starting-week</VAR> -> <VAR>integer</VAR> +- <DD class=proc-def>The ordinal week of the year which holds this date, ignoring a first partial week. 'Day-of-week-starting-week' is the integer corresponding to the day of the week which is to be considered the first day of the week (Sunday=0, Monday=1, etc.). +-</DL> +- +-<H2>Time/Date/Julian Day/Modified Julian Day Converters</h2> ++</p><p> The following procedures are required: ++</p> ++<dl> ++ <dt class="proc-def" id="time<=-p"><code class="proc-def">time<=?</code> <var>time1 time2</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if <var>time1</var> is before or at (less than or equal to) <var>time2</var>, <code>#f</code> otherwise. ++ </dd><dt class="proc-def" id="time<-p"><code class="proc-def">time<?</code> <var>time1 time2</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if <var>time1</var> is before (less than) <var>time2</var>, <code>#f</code> otherwise. ++ </dd><dt class="proc-def" id="time=-p"><code class="proc-def">time=?</code> <var>time1 time2</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if <var>time1</var> at (equal) <var>time2</var>, <code>#f</code> otherwise. ++ </dd><dt class="proc-def" id="time>=-p"><code class="proc-def">time>=?</code> <var>time1 time2</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if <var>time1</var> is at or after (greater than or equal to) <var>time2</var>, <code>#f</code> otherwise. ++ </dd><dt class="proc-def" id="time>-p"><code class="proc-def">time>?</code> <var>time1 time2</var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if <var>time1</var> is after (greater than) <var>time2</var>, <code>#f</code> otherwise. ++</dd></dl> ++ ++<h3>Time arithmetic procedures</h3> ++ ++<p>The following procedures are required. ++</p> ++<dl> ++ <dt class="proc-def" id="time-difference"><code class="proc-def">time-difference</code> <var>time1 time2</var> -> <var>time-duration</var> ++ </dt><dd class="proc-def">The <code>TIME-DURATION</code> between <var>time1</var> and <var>time2</var>. It is an error if <var>time1</var> and <var>time2</var> are of different time types. A new time object is created. ++ </dd><dt class="proc-def" id="time-difference!"><code class="proc-def">time-difference!</code> <var>time1 time2</var> -> <var>time-duration</var> ++ </dt><dd class="proc-def">The <code>TIME-DURATION</code> between <var>time1</var> and <var>time2</var>. It is an error if <var>time1</var> and <var>time2</var> are of different time types. <var>Time1</var> may be used to create the resulting <code>TIME-DURATION</code> object. ++ </dd><dt class="proc-def" id="add-duration"><code class="proc-def">add-duration</code> <var>time1 time-duration</var> -> <var>time</var> ++ </dt><dd class="proc-def">The time resulting from adding <var>time-duration</var> to <var>time1</var>, which is a time object of the same time type as <var>time1</var>. A new time object is created. ++ </dd><dt class="proc-def" id="add-duration!"><code class="proc-def">add-duration!</code> <var>time1 time-duration</var> -> <var>time</var> ++ </dt><dd class="proc-def">The time resulting from adding <var>time-duration</var> to <var>time1</var>, which is a time object of the same time type as <var>time1</var>. <var>Time1</var> may used to create the resulting time object. ++ </dd><dt class="proc-def" id="subtract-duration"><code class="proc-def">subtract-duration</code> <var>time1 time-duration</var> -> <var>time</var> ++ </dt><dd class="proc-def">The time resulting from subtracting <var>time-duration</var> to <var>time1</var>, which is a time object of the same time type as <var>time1</var>. A new time object is created. ++ </dd><dt class="proc-def" id="subtract-duration!"><code class="proc-def">subtract-duration!</code> <var>time1 time-duration</var> -> <var>time</var> ++ </dt><dd class="proc-def">The time resulting from subtracting <var>time-duration</var> to <var>time1</var>, which is a time object of the same time type as <var>time1</var>. <var>Time1</var> may used to create the resulting time object. ++</dd></dl> ++ ++<h3>Date object and accessors</h3> ++ ++<p>Date objects are immutable once created. The following procedures are required. ++</p> ++<dl> ++ <dt class="proc-def" id="make-date"><code class="proc-def">make-date</code> <var>nanosecond second minute hour day month year zone-offset</var> -> <var>date</var> ++ </dt><dd class="proc-def">Creates a date object. ++ </dd><dt class="proc-def" id="date-p"><code class="proc-def">date?</code> <var>date </var> -> <var>boolean</var> ++ </dt><dd class="proc-def"><code>#t</code> if object is a time object, otherwise, <code>#f</code>. ++ </dd><dt class="proc-def" id="date-nanosecond"><code class="proc-def">date-nanosecond</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date nanosecond. ++ </dd><dt class="proc-def" id="date-second"><code class="proc-def">date-second</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date second. ++ </dd><dt class="proc-def" id="date-minute"><code class="proc-def">date-minute</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date minute. ++ </dd><dt class="proc-def" id="date-hour"><code class="proc-def">date-hour</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date hour. ++ </dd><dt class="proc-def" id="date-day"><code class="proc-def">date-day</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date day. ++ </dd><dt class="proc-def" id="date-month"><code class="proc-def">date-month</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date month. ++ </dd><dt class="proc-def" id="date-year"><code class="proc-def">date-year</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date year. ++ </dd><dt class="proc-def" id="date-zone-offset"><code class="proc-def">date-zone-offset</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">Date time zone offset. ++ </dd><dt class="proc-def" id="date-year-day"><code class="proc-def">date-year-day</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">The ordinal day of the year of this date. January 1 is 1, etc. ++ </dd><dt class="proc-def" id="date-week-day"><code class="proc-def">date-week-day</code> <var>date</var> -> <var>integer</var> ++ </dt><dd class="proc-def">The day of the week of this date, where Sunday=0, Monday=1, etc. ++ </dd><dt class="proc-def" id="date-week-number"><code class="proc-def">date-week-number</code> <var>date day-of-week-starting-week</var> -> <var>integer</var> ++ </dt><dd class="proc-def">The ordinal week of the year which holds this date, ignoring a first partial week. 'Day-of-week-starting-week' is the integer corresponding to the day of the week which is to be considered the first day of the week (Sunday=0, Monday=1, etc.). ++</dd></dl> ++ ++<h3>Time/Date/Julian Day/Modified Julian Day Converters</h3> + + The following conversion procedures are required. +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="date->julian-day">date->julian-day</a></CODE> <VAR>date</VAR> -> <VAR>jd</VAR> +- <DD class=proc-def>Convert date to Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="date->modified-julian-day">date->modified-julian-day</a></CODE> <VAR>date</VAR> -> <VAR>mjd</VAR> +- <DD class=proc-def>Convert date to Modified Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="date->time-monotonic">date->time-monotonic</a></CODE> <VAR>date</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert date to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="date->time-tai">date->time-tai</a></CODE> <VAR>date</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert date to TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="date->time-utc">date->time-utc</a></CODE> <VAR>date</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert date to UTC time. +- <DT class=proc-def><CODE class=proc-def><a name="julian-day->date">julian-day->date</a></CODE> <VAR>jd</VAR> [<VAR>tz-offset</VAR>] -> <VAR>date</VAR> +- <DD class=proc-def>Convert Julian Day to date, , using time zone offset, which defaults to the local time zone. +- <DT class=proc-def><CODE class=proc-def><a name="julian-day->time-monotonic">julian-day->time-monotonic</a></CODE> <VAR>jd</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert Julian Day to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="julian-day->time-tai">julian-day->time-tai</a></CODE> <VAR>jd</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert Julian Day to TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="julian-day->time-utc">julian-day->time-utc</a></CODE> <VAR>jd</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert Julian Day to UTC time. +- <DT class=proc-def><CODE class=proc-def><a name="modified-julian-day->date">modified-julian-day->date</a></CODE> <VAR>mjd</VAR> [<VAR>tz-offset</VAR>] -> <VAR>date</VAR> +- <DD class=proc-def>Convert Modified Julian Day to date, using time zone offset, which defaults to the local time zone. +- <DT class=proc-def><CODE class=proc-def><a name="modified-julian-day->time-monotonic">modified-julian-day->time-monotonic</a></CODE> <VAR>mjd</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert Modified Julian Day to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="modified-julian-day->time-tai">modified-julian-day->time-tai</a></CODE> <VAR>mjd</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert Modified Julian Day to TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="modified-julian-day->time-utc">modified-julian-day->time-utc</a></CODE> <VAR>mjd</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert Modified Julian Day to UTC time. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->date">time-monotonic->date</a></CODE> <VAR>time-monotonic</VAR> [<VAR>tz-offset</VAR>] -> <VAR>date</VAR> +- <DD class=proc-def>Convert monotonic time to date, using time zone offset, which defaults to the local time zone. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->julian-day">time-monotonic->julian-day</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>jd</VAR> +- <DD class=proc-def>Convert monotonic time to Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->modified-julian-day">time-monotonic->modified-julian-day</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>mjd</VAR> +- <DD class=proc-def>Convert monotonic time to Modified Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->time-tai">time-monotonic->time-tai</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert monotonic time to TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->time-tai!">time-monotonic->time-tai!</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert monotonic time to TAI time. The time structure may be reused. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->time-utc">time-monotonic->time-utc</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert monotonic time to UTC time. +- <DT class=proc-def><CODE class=proc-def><a name="time-monotonic->time-utc!">time-monotonic->time-utc!</a></CODE> <VAR>time-monotonic</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert monotonic time to UTC time. The time structure may be reused. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->date">time-tai->date</a></CODE> <VAR>time-tai [tz-offset]</VAR> -> <VAR>date</VAR> +- <DD class=proc-def>Convert TAI time to date, using time zone offset, which defaults to the local time zone. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->julian-day">time-tai->julian-day</a></CODE> <VAR>time-tai</VAR> -> <VAR>jd</VAR> +- <DD class=proc-def>Convert TAI time to Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->modified-julian-day">time-tai->modified-julian-day</a></CODE> <VAR>time-tai</VAR> -> <VAR>mjd</VAR> +- <DD class=proc-def>Convert TAI time to Modified Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->time-monotonic">time-tai->time-monotonic</a></CODE> <VAR>time-tai</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert TAI time to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->time-monotonic!">time-tai->time-monotonic!</a></CODE> <VAR>time-tai</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert TAI time to monotonic time. The time structure may be reused. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->time-utc">time-tai->time-utc</a></CODE> <VAR>time-tai</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert TAI time to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="time-tai->time-utc!">time-tai->time-utc!</a></CODE> <VAR>time-tai</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert TAI time to monotonic time. The time structure may be reused. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->date">time-utc->date</a></CODE> <VAR>time-utc [tz-offset]</VAR> -> <VAR>time-utc</VAR> +- <DD class=proc-def>Convert UTC time to date, using time zone offset, which defaults to the local time zone. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->julian-day">time-utc->julian-day</a></CODE> <VAR>time-utc</VAR> -> <VAR>jd</VAR> +- <DD class=proc-def>Convert UTC time to Julian Day +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->modified-julian-day">time-utc->modified-julian-day</a></CODE> <VAR>time-utc</VAR> -> <VAR>mjd</VAR> +- <DD class=proc-def>Convert UTC time to Modified Julian Day. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->time-monotonic">time-utc->time-monotonic</a></CODE> <VAR>time-utc</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert UTC time to monotonic time. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->time-monotonic!">time-utc->time-monotonic!</a></CODE> <VAR>time-utc</VAR> -> <VAR>time-monotonic</VAR> +- <DD class=proc-def>Convert UTC time to monotonic time. The time structure may be reused. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->time-tai">time-utc->time-tai</a></CODE> <VAR>time-utc</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert UTC time to TAI time. +- <DT class=proc-def><CODE class=proc-def><a name="time-utc->time-tai!">time-utc->time-tai!</a></CODE> <VAR>time-utc</VAR> -> <VAR>time-tai</VAR> +- <DD class=proc-def>Convert UTC time to TAI time. The time structure may be reused. +-</DL> +- +-<h2>Date to String/String to Date Converters</h2> ++<dl> ++ <dt class="proc-def" id="date->julian-day"><code class="proc-def">date->julian-day</code> <var>date</var> -> <var>jd</var> ++ </dt><dd class="proc-def">Convert date to Julian Day. ++ </dd><dt class="proc-def" id="date->modified-julian-day"><code class="proc-def">date->modified-julian-day</code> <var>date</var> -> <var>mjd</var> ++ </dt><dd class="proc-def">Convert date to Modified Julian Day. ++ </dd><dt class="proc-def" id="date->time-monotonic"><code class="proc-def">date->time-monotonic</code> <var>date</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert date to monotonic time. ++ </dd><dt class="proc-def" id="date->time-tai"><code class="proc-def">date->time-tai</code> <var>date</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert date to TAI time. ++ </dd><dt class="proc-def" id="date->time-utc"><code class="proc-def">date->time-utc</code> <var>date</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert date to UTC time. ++ </dd><dt class="proc-def" id="julian-day->date"><code class="proc-def">julian-day->date</code> <var>jd</var> [<var>tz-offset</var>] -> <var>date</var> ++ </dt><dd class="proc-def">Convert Julian Day to date, , using time zone offset, which defaults to the local time zone. ++ </dd><dt class="proc-def" id="julian-day->time-monotonic"><code class="proc-def">julian-day->time-monotonic</code> <var>jd</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert Julian Day to monotonic time. ++ </dd><dt class="proc-def" id="julian-day->time-tai"><code class="proc-def">julian-day->time-tai</code> <var>jd</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert Julian Day to TAI time. ++ </dd><dt class="proc-def" id="julian-day->time-utc"><code class="proc-def">julian-day->time-utc</code> <var>jd</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert Julian Day to UTC time. ++ </dd><dt class="proc-def" id="modified-julian-day->date"><code class="proc-def">modified-julian-day->date</code> <var>mjd</var> [<var>tz-offset</var>] -> <var>date</var> ++ </dt><dd class="proc-def">Convert Modified Julian Day to date, using time zone offset, which defaults to the local time zone. ++ </dd><dt class="proc-def" id="modified-julian-day->time-monotonic"><code class="proc-def">modified-julian-day->time-monotonic</code> <var>mjd</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert Modified Julian Day to monotonic time. ++ </dd><dt class="proc-def" id="modified-julian-day->time-tai"><code class="proc-def">modified-julian-day->time-tai</code> <var>mjd</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert Modified Julian Day to TAI time. ++ </dd><dt class="proc-def" id="modified-julian-day->time-utc"><code class="proc-def">modified-julian-day->time-utc</code> <var>mjd</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert Modified Julian Day to UTC time. ++ </dd><dt class="proc-def" id="time-monotonic->date"><code class="proc-def">time-monotonic->date</code> <var>time-monotonic</var> [<var>tz-offset</var>] -> <var>date</var> ++ </dt><dd class="proc-def">Convert monotonic time to date, using time zone offset, which defaults to the local time zone. ++ </dd><dt class="proc-def" id="time-monotonic->julian-day"><code class="proc-def">time-monotonic->julian-day</code> <var>time-monotonic</var> -> <var>jd</var> ++ </dt><dd class="proc-def">Convert monotonic time to Julian Day. ++ </dd><dt class="proc-def" id="time-monotonic->modified-julian-day"><code class="proc-def">time-monotonic->modified-julian-day</code> <var>time-monotonic</var> -> <var>mjd</var> ++ </dt><dd class="proc-def">Convert monotonic time to Modified Julian Day. ++ </dd><dt class="proc-def" id="time-monotonic->time-tai"><code class="proc-def">time-monotonic->time-tai</code> <var>time-monotonic</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert monotonic time to TAI time. ++ </dd><dt class="proc-def" id="time-monotonic->time-tai!"><code class="proc-def">time-monotonic->time-tai!</code> <var>time-monotonic</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert monotonic time to TAI time. The time structure may be reused. ++ </dd><dt class="proc-def" id="time-monotonic->time-utc"><code class="proc-def">time-monotonic->time-utc</code> <var>time-monotonic</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert monotonic time to UTC time. ++ </dd><dt class="proc-def" id="time-monotonic->time-utc!"><code class="proc-def">time-monotonic->time-utc!</code> <var>time-monotonic</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert monotonic time to UTC time. The time structure may be reused. ++ </dd><dt class="proc-def" id="time-tai->date"><code class="proc-def">time-tai->date</code> <var>time-tai [tz-offset]</var> -> <var>date</var> ++ </dt><dd class="proc-def">Convert TAI time to date, using time zone offset, which defaults to the local time zone. ++ </dd><dt class="proc-def" id="time-tai->julian-day"><code class="proc-def">time-tai->julian-day</code> <var>time-tai</var> -> <var>jd</var> ++ </dt><dd class="proc-def">Convert TAI time to Julian Day. ++ </dd><dt class="proc-def" id="time-tai->modified-julian-day"><code class="proc-def">time-tai->modified-julian-day</code> <var>time-tai</var> -> <var>mjd</var> ++ </dt><dd class="proc-def">Convert TAI time to Modified Julian Day. ++ </dd><dt class="proc-def" id="time-tai->time-monotonic"><code class="proc-def">time-tai->time-monotonic</code> <var>time-tai</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert TAI time to monotonic time. ++ </dd><dt class="proc-def" id="time-tai->time-monotonic!"><code class="proc-def">time-tai->time-monotonic!</code> <var>time-tai</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert TAI time to monotonic time. The time structure may be reused. ++ </dd><dt class="proc-def" id="time-tai->time-utc"><code class="proc-def">time-tai->time-utc</code> <var>time-tai</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert TAI time to monotonic time. ++ </dd><dt class="proc-def" id="time-tai->time-utc!"><code class="proc-def">time-tai->time-utc!</code> <var>time-tai</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert TAI time to monotonic time. The time structure may be reused. ++ </dd><dt class="proc-def" id="time-utc->date"><code class="proc-def">time-utc->date</code> <var>time-utc [tz-offset]</var> -> <var>time-utc</var> ++ </dt><dd class="proc-def">Convert UTC time to date, using time zone offset, which defaults to the local time zone. ++ </dd><dt class="proc-def" id="time-utc->julian-day"><code class="proc-def">time-utc->julian-day</code> <var>time-utc</var> -> <var>jd</var> ++ </dt><dd class="proc-def">Convert UTC time to Julian Day ++ </dd><dt class="proc-def" id="time-utc->modified-julian-day"><code class="proc-def">time-utc->modified-julian-day</code> <var>time-utc</var> -> <var>mjd</var> ++ </dt><dd class="proc-def">Convert UTC time to Modified Julian Day. ++ </dd><dt class="proc-def" id="time-utc->time-monotonic"><code class="proc-def">time-utc->time-monotonic</code> <var>time-utc</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert UTC time to monotonic time. ++ </dd><dt class="proc-def" id="time-utc->time-monotonic!"><code class="proc-def">time-utc->time-monotonic!</code> <var>time-utc</var> -> <var>time-monotonic</var> ++ </dt><dd class="proc-def">Convert UTC time to monotonic time. The time structure may be reused. ++ </dd><dt class="proc-def" id="time-utc->time-tai"><code class="proc-def">time-utc->time-tai</code> <var>time-utc</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert UTC time to TAI time. ++ </dd><dt class="proc-def" id="time-utc->time-tai!"><code class="proc-def">time-utc->time-tai!</code> <var>time-utc</var> -> <var>time-tai</var> ++ </dt><dd class="proc-def">Convert UTC time to TAI time. The time structure may be reused. ++</dd></dl> ++ ++<h3>Date to String/String to Date Converters</h3> + + These procedures provide conversion to and from strings. They are required. The specification below describes a 'locale;' the + specification of locales is beyond this SRFI. + +-<DL> +- <DT class=proc-def><CODE class=proc-def><a name="date->string">date->string</a></CODE> <VAR>date</VAR> [<VAR>format-string</VAR>] -> <VAR>string</VAR> +- <DD class=proc-def>Converts a date to a string, using the format string. The format string is copied as is; except +-escape characters (indicated by the tilde) are replaced with specific conversions. Table 1 lists the required conversion specifiers; +-implementations are free to extend this list. +- <DT class=proc-def><CODE class=proc-def><a name="string->date">string->date</a></CODE> <VAR>input-string template-string</VAR> -> <VAR>date</VAR> +- <DD class=proc-def>Converts an input string to a date, using the template string. The input string must match the template +-sting as is; except escape characters (indicate by the tilde) indicate special converters which (1) move to the next character in the input string fulfilling a criterion; (2) read a value, and (3) act on this value in some way. Table 2 lists the required +-converters; implementations are free to extend this list. +-</DL> +- +-<H3>PLT-specific extensions</H3> +- +-<p>The <code>~?</code> wildcard is specific to the PLT implementation of <code>string->date</code>: it parses 1 and 2 digit years like <code>~y</code> and 3 and 4 digit years like <code>~Y</code>.</p> +- +-<TABLE ALIGN="CENTER" WIDTH="80%" summary="DATE->STRING conversion specifiers"> +-<TR><TD COLSPAN="2"><HR WIDTH="100%"></TD></TR> +-<TR><TH>Ch</TH><TH>Conversion</TH></TR> +-<TR><TD COLSPAN="2"><HR WIDTH="100%"></TD></TR> +-<TR><TD width="5%"><code>~~</code></TD><TD WIDTH="95%">a literal <CODE>~</CODE></TD></TR> +-<TR><TD width="5%"><code>~a</code></TD><TD WIDTH="95%">locale's abbreviated weekday name (Sun...Sat)</TD></TR> +-<TR><TD width="5%"><code>~A</code></TD><TD WIDTH="95%">locale's full weekday name (Sunday...Saturday)</TD></TR> +-<TR><TD width="5%"><code>~b</code></TD><TD WIDTH="95%">locale's abbreviate month name (Jan...Dec)</TD></TR> +-<TR><TD width="5%"><code>~B</code></TD><TD WIDTH="95%">locale's full month day (January...December)</TD></TR> +-<TR><TD width="5%"><code>~c</code></TD><TD WIDTH="95%">locale's date and time (e.g., "Fri Jul 14 20:28:42-0400 2000") </TD></TR> +-<TR><TD width="5%"><code>~d</code></TD><TD WIDTH="95%">day of month, zero padded (01...31)</TD></TR> +-<TR><TD width="5%"><code>~D</code></TD><TD WIDTH="95%">date (mm/dd/yy)</TD></TR> +-<TR><TD width="5%"><code>~e</code></TD><TD WIDTH="95%">day of month, blank padded ( 1...31)</TD></TR> +-<TR><TD width="5%"><code>~f</code></TD><TD WIDTH="95%">seconds+fractional seconds, using locale's decimal separator (e.g. 5.2).</TD></TR> +-<TR><TD width="5%"><code>~h</code></TD><TD WIDTH="95%">same as ~b</TD></TR> +-<TR><TD width="5%"><code>~H</code></TD><TD WIDTH="95%">hour, zero padded, 24-hour clock (00...23)</TD></TR> +-<TR><TD width="5%"><code>~I</code></TD><TD WIDTH="95%">hour, zero padded, 12-hour clock (01...12)</TD></TR> +-<TR><TD width="5%"><code>~j</code></TD><TD WIDTH="95%">day of year, zero padded</TD></TR> +-<TR><TD width="5%"><code>~k</code></TD><TD WIDTH="95%">hour, blank padded, 24-hour clock (00...23)</TD></TR> +-<TR><TD width="5%"><code>~l</code></TD><TD WIDTH="95%">hour, blank padded, 12-hour clock (01...12)</TD></TR> +-<TR><TD width="5%"><code>~m</code></TD><TD WIDTH="95%">month, zero padded (01...12)</TD></TR> +-<TR><TD width="5%"><code>~M</code></TD><TD WIDTH="95%">minute, zero padded (00...59)</TD></TR> +-<TR><TD width="5%"><code>~n</code></TD><TD WIDTH="95%">new line</TD></TR> +-<TR><TD width="5%"><code>~N</code></TD><TD WIDTH="95%">nanosecond, zero padded</TD></TR> +-<TR><TD width="5%"><code>~p</code></TD><TD WIDTH="95%">locale's AM or PM</TD></TR> +-<TR><TD width="5%"><code>~r</code></TD><TD WIDTH="95%">time, 12 hour clock, same as "~I:~M:~S ~p"</TD></TR> +-<TR><TD width="5%"><code>~s</code></TD><TD WIDTH="95%">number of full seconds since "the epoch" (in UTC)</TD></TR> +-<TR><TD width="5%"><code>~S</code></TD><TD WIDTH="95%">second, zero padded (00...60)</TD></TR> +-<TR><TD width="5%"><code>~t</code></TD><TD WIDTH="95%">horizontal tab</TD></TR> +-<TR><TD width="5%"><code>~T</code></TD><TD WIDTH="95%">time, 24 hour clock, same as "~H:~M:~S"</TD></TR> +-<TR><TD width="5%"><code>~U</code></TD><TD WIDTH="95%">week number of year with Sunday as first day of week (00...53)</TD></TR> +-<TR><TD width="5%"><code>~V</code></TD><TD WIDTH="95%">week number of year with Monday as first day of week (01...52)</TD></TR> +-<TR><TD width="5%"><code>~w</code></TD><TD WIDTH="95%"> day of week (0...6)</TD></TR> +-<TR><TD width="5%"><code>~W</code></TD><TD WIDTH="95%">week number of year with Monday as first day of week (01...52)</TD></TR> +-<TR><TD width="5%"><code>~x</code></TD><TD WIDTH="95%">week number of year with Monday as first day of week (00...53)</TD></TR> +-<TR><TD width="5%"><code>~X</code></TD><TD WIDTH="95%">locale's date representation, for example: "07/31/00" </TD></TR> +-<TR><TD width="5%"><code>~y</code></TD><TD WIDTH="95%">last two digits of year (00...99)</TD></TR> +-<TR><TD width="5%"><code>~Y</code></TD><TD WIDTH="95%">year</TD></TR> +-<TR><TD width="5%"><code>~z</code></TD><TD WIDTH="95%">time zone in RFC-822 style</TD></TR> +-<TR><TD width="5%"><code>~Z</code></TD><TD WIDTH="95%">symbol time zone (not-implemented)</TD></TR> +-<TR><TD width="5%"><code>~1</code></TD><TD WIDTH="95%">ISO-8601 year-month-day format</TD></TR> +-<TR><TD width="5%"><code>~2</code></TD><TD WIDTH="95%">ISO-8601 hour-minute-second-timezone format</TD></TR> +-<TR><TD width="5%"><code>~3</code></TD><TD WIDTH="95%">ISO-8601 hour-minute-second format</TD></TR> +-<TR><TD width="5%"><code>~4</code></TD><TD WIDTH="95%">ISO-8601 year-month-day-hour-minute-second-timezone format</TD></TR> +-<TR><TD width="5%"><code>~5</code></TD><TD WIDTH="95%">ISO-8601 year-month-day-hour-minute-second format</TD></TR> +-<TR><TD COLSPAN="2"><HR WIDTH="100%"></TD></TR> +-<TR><TH COLSPAN="2">Table 1: <code>DATE->STRING</code> conversion specifiers</TH></TR> +-<TR><TD COLSPAN="2"><HR WIDTH="100%"></TD></TR> +-</TABLE> +- +-<p> +-<TABLE ALIGN="CENTER" WIDTH="80%" summary="STRING->DATE conversion specifiers"> +-<TR><TD COLSPAN="4"><HR WIDTH="100%"></TD></TR> +-<TR><TH>Ch</TH><TH>Skip to</TH><TH>Read</TH><TH>Set</TH></TR> +-<TR><TD COLSPAN="4"><HR WIDTH="100%"></TD></TR> +-<TR><TD width="6%"><code>~~</code></TD><TD WIDTH="23%">any</TD><TD WIDTH="50%">read literal <code>~</code></TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~a</code></TD><TD WIDTH="23%">char-alphabetic?</TD><TD WIDTH="50%">abbreviated weekday in locale</TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~A</code></TD><TD WIDTH="23%">char-alphabetic?</TD><TD WIDTH="50%">full weekday in locale</TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~b</code></TD><TD WIDTH="23%">char-alphabetic?</TD><TD WIDTH="50%">abbreviated month name in locale</TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~B</code></TD><TD WIDTH="23%">char-alphabetic?</TD><TD WIDTH="50%">full month name in locale</TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~d</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">day of month</TD><TD WIDTH="23%"><code>date-day</code></TD></TR> +-<TR><TD width="6%"><code>~e</code></TD><TD WIDTH="23%">any</TD><TD WIDTH="50%">day of month, blank padded</TD><TD WIDTH="23%"><code>date-day</code></TD></TR> +-<TR><TD width="6%"><code>~h</code></TD><TD WIDTH="23%">char-alphabetic?</TD><TD WIDTH="50%">same as ~b</TD><TD WIDTH="23%">nothing</TD></TR> +-<TR><TD width="6%"><code>~H</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">hour</TD><TD WIDTH="23%"><code>date-hour</code></TD></TR> +-<TR><TD width="6%"><code>~k</code></TD><TD WIDTH="23%">any</TD><TD WIDTH="50%">hour, blank padded</TD><TD WIDTH="23%"><code>date-hour</code></TD></TR> +-<TR><TD width="6%"><code>~m</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">month</TD><TD WIDTH="23%"><code>date-month</code></TD></TR> +-<TR><TD width="6%"><code>~M</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">minute</TD><TD WIDTH="23%"><code>date-minute</code></TD></TR> +-<TR><TD width="6%"><code>~S</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">second</TD><TD WIDTH="23%"><code>date-second</code></TD></TR> +-<TR><TD width="6%"><code>~y</code></TD><TD WIDTH="23%">any</TD><TD WIDTH="50%">2-digit year</TD><TD WIDTH="23%"><code>date-year</code> within 50 years</TD></TR> +-<TR><TD width="6%"><code>~Y</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">year</TD><TD WIDTH="23%"><code>date-year</code></TD></TR> +-<TR><TD width="6%"><code>~z</code></TD><TD WIDTH="23%">any</TD><TD WIDTH="50%">time zone</TD><TD WIDTH="23%"><code>date-zone-offset</code></TD></TR> +-<TR><TD width="6%"><code>~?</code></TD><TD WIDTH="23%">char-numeric?</TD><TD WIDTH="50%">2-digit or 4-digit year (PLT-specific extension)</TD><TD WIDTH="23%"><code>date-year</code></TD></TR> +-<TR><TD COLSPAN="4"><HR WIDTH="100%"></TD></TR> +-<TR><TH COLSPAN="4">Table 2: <code>STRING->DATE</code> conversion specifiers</TH></TR> +-<TR><TD COLSPAN="4"><HR WIDTH="100%"></TD></TR> +-</TABLE> +- +-<H1>Implementation</H1> ++<dl> ++ <dt class="proc-def" id="date->string"><code class="proc-def">date->string</code> <var>date</var> [<var>format-string</var>] -> <var>string</var> ++ </dt> ++ <dd class="proc-def"> ++ <p> ++ Converts a date to a string, using the format string. The format string ++ is copied as is; except escape characters (indicated by the tilde) are ++ replaced with specific conversions. Table 1 lists the required ++ conversion specifiers; implementations are free to extend this list. ++ </p> ++ </dd> ++ <dt class="proc-def" id="string->date"><code class="proc-def">string->date</code> <var>input-string template-string</var> -> <var>date</var> ++ </dt> ++ <dd class="proc-def"> ++ <p> ++ Converts an input string to a date, using the template string. The input ++ string must match the template sting as is; except escape characters ++ (indicate by the tilde) indicate special converters which (1) move to ++ the next character in the input string fulfilling a criterion; (2) read ++ a value, and (3) act on this value in some way. Table 2 lists the ++ required converters; implementations are free to extend this list. ++ </p> ++ <p class="srfi-plt-extension"><b>PLT-specific extension:</b> The <code>~?</code> wildcard is ++specific to the PLT implementation of <code>string->date</code>: ++it parses 1 and 2 digit years like <code>~y</code> and 3 and 4 ++digit years like <code>~Y</code>.</p></dd> ++</dl> ++ ++<table align="CENTER" summary="DATE->STRING conversion specifiers" width="80%"> ++<tr><td colspan="2"><hr width="100%" /></td></tr> ++<tr><th>Ch</th><th>Conversion</th></tr> ++<tr><td colspan="2"><hr width="100%" /></td></tr> ++<tr><td width="5%"><code>~~</code></td><td width="95%">a literal <code>~</code></td></tr> ++<tr><td width="5%"><code>~a</code></td><td width="95%">locale's abbreviated weekday name (Sun...Sat)</td></tr> ++<tr><td width="5%"><code>~A</code></td><td width="95%">locale's full weekday name (Sunday...Saturday)</td></tr> ++<tr><td width="5%"><code>~b</code></td><td width="95%">locale's abbreviate month name (Jan...Dec)</td></tr> ++<tr><td width="5%"><code>~B</code></td><td width="95%">locale's full month day (January...December)</td></tr> ++<tr><td width="5%"><code>~c</code></td><td width="95%">locale's date and time (e.g., "Fri Jul 14 20:28:42-0400 2000") </td></tr> ++<tr><td width="5%"><code>~d</code></td><td width="95%">day of month, zero padded (01...31)</td></tr> ++<tr><td width="5%"><code>~D</code></td><td width="95%">date (mm/dd/yy)</td></tr> ++<tr><td width="5%"><code>~e</code></td><td width="95%">day of month, blank padded ( 1...31)</td></tr> ++<tr><td width="5%"><code>~f</code></td><td width="95%">seconds+fractional seconds, using locale's decimal separator (e.g. 5.2).</td></tr> ++<tr><td width="5%"><code>~h</code></td><td width="95%">same as ~b</td></tr> ++<tr><td width="5%"><code>~H</code></td><td width="95%">hour, zero padded, 24-hour clock (00...23)</td></tr> ++<tr><td width="5%"><code>~I</code></td><td width="95%">hour, zero padded, 12-hour clock (01...12)</td></tr> ++<tr><td width="5%"><code>~j</code></td><td width="95%">day of year, zero padded</td></tr> ++<tr><td width="5%"><code>~k</code></td><td width="95%">hour, blank padded, 24-hour clock ( 0...23)</td></tr> ++<tr><td width="5%"><code>~l</code></td><td width="95%">hour, blank padded, 12-hour clock ( 1...12)</td></tr> ++<tr><td width="5%"><code>~m</code></td><td width="95%">month, zero padded (01...12)</td></tr> ++<tr><td width="5%"><code>~M</code></td><td width="95%">minute, zero padded (00...59)</td></tr> ++<tr><td width="5%"><code>~n</code></td><td width="95%">new line</td></tr> ++<tr><td width="5%"><code>~N</code></td><td width="95%">nanosecond, zero padded</td></tr> ++<tr><td width="5%"><code>~p</code></td><td width="95%">locale's AM or PM</td></tr> ++<tr><td width="5%"><code>~r</code></td><td width="95%">time, 12 hour clock, same as "~I:~M:~S ~p"</td></tr> ++<tr><td width="5%"><code>~s</code></td><td width="95%">number of full seconds since "the epoch" (in UTC)</td></tr> ++<tr><td width="5%"><code>~S</code></td><td width="95%">second, zero padded (00...60)</td></tr> ++<tr><td width="5%"><code>~t</code></td><td width="95%">horizontal tab</td></tr> ++<tr><td width="5%"><code>~T</code></td><td width="95%">time, 24 hour clock, same as "~H:~M:~S"</td></tr> ++<tr><td width="5%"><code>~U</code></td><td width="95%">week number of year with Sunday as first day of week (00...53)</td></tr> ++<tr><td width="5%"><code>~V</code></td><td width="95%">ISO 8601 week number of the year with Monday as first day of week (01..53)<sup><a href="#errata-footnote-1">[1]</a></sup></td></tr> ++<tr><td width="5%"><code>~w</code></td><td width="95%"> day of week (0...6)</td></tr> ++<tr><td width="5%"><code>~W</code></td><td width="95%">week number of year with Monday as first day of week (01...52)</td></tr> ++<tr><td width="5%"><code>~x</code></td><td width="95%">locale's date representation<sup><a href="#errata-footnote-1">[1]</a></sup></td></tr> ++<tr><td width="5%"><code>~X</code></td><td width="95%">locale's time representation<sup><a href="#errata-footnote-1">[1]</a></sup></td></tr> ++<tr><td width="5%"><code>~y</code></td><td width="95%">last two digits of year (00...99)</td></tr> ++<tr><td width="5%"><code>~Y</code></td><td width="95%">year</td></tr> ++<tr><td width="5%"><code>~z</code></td><td width="95%">time zone in RFC-822 style</td></tr> ++<tr><td width="5%"><code>~Z</code></td><td width="95%">symbol time zone (not-implemented)</td></tr> ++<tr><td width="5%"><code>~1</code></td><td width="95%">ISO-8601 year-month-day format</td></tr> ++<tr><td width="5%"><code>~2</code></td><td width="95%">ISO-8601 hour-minute-second-timezone format</td></tr> ++<tr><td width="5%"><code>~3</code></td><td width="95%">ISO-8601 hour-minute-second format</td></tr> ++<tr><td width="5%"><code>~4</code></td><td width="95%">ISO-8601 year-month-day-hour-minute-second-timezone format</td></tr> ++<tr><td width="5%"><code>~5</code></td><td width="95%">ISO-8601 year-month-day-hour-minute-second format</td></tr> ++<tr><td colspan="2"><hr width="100%" /></td></tr> ++<tr><th colspan="2">Table 1: <code>DATE->STRING</code> conversion specifiers</th></tr> ++<tr><td colspan="2"><hr width="100%" /></td></tr> ++</table> ++ ++<p id="errata-footnote-1" style="margin-left: 5em;"><sup>[1]</sup> These lines were changed as part of a fix to errata on 2009-06-11.</p> ++ ++<table align="CENTER" summary="STRING->DATE conversion specifiers" width="80%"> ++<tr><td colspan="4"><hr width="100%" /></td></tr> ++<tr><th>Ch</th><th>Skip to</th><th>Read</th><th>Set</th></tr> ++<tr><td colspan="4"><hr width="100%" /></td></tr> ++<tr><td width="6%"><code>~~</code></td><td width="23%">any</td><td width="50%">read literal <code>~</code></td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~a</code></td><td width="23%">char-alphabetic?</td><td width="50%">abbreviated weekday in locale</td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~A</code></td><td width="23%">char-alphabetic?</td><td width="50%">full weekday in locale</td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~b</code></td><td width="23%">char-alphabetic?</td><td width="50%">abbreviated month name in locale</td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~B</code></td><td width="23%">char-alphabetic?</td><td width="50%">full month name in locale</td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~d</code></td><td width="23%">char-numeric?</td><td width="50%">day of month</td><td width="23%"><code>date-day</code></td></tr> ++<tr><td width="6%"><code>~e</code></td><td width="23%">any</td><td width="50%">day of month, blank padded</td><td width="23%"><code>date-day</code></td></tr> ++<tr><td width="6%"><code>~h</code></td><td width="23%">char-alphabetic?</td><td width="50%">same as ~b</td><td width="23%">nothing</td></tr> ++<tr><td width="6%"><code>~H</code></td><td width="23%">char-numeric?</td><td width="50%">hour</td><td width="23%"><code>date-hour</code></td></tr> ++<tr><td width="6%"><code>~k</code></td><td width="23%">any</td><td width="50%">hour, blank padded</td><td width="23%"><code>date-hour</code></td></tr> ++<tr><td width="6%"><code>~m</code></td><td width="23%">char-numeric?</td><td width="50%">month</td><td width="23%"><code>date-month</code></td></tr> ++<tr><td width="6%"><code>~M</code></td><td width="23%">char-numeric?</td><td width="50%">minute</td><td width="23%"><code>date-minute</code></td></tr> ++<tr><td width="6%"><code>~S</code></td><td width="23%">char-numeric?</td><td width="50%">second</td><td width="23%"><code>date-second</code></td></tr> ++<tr><td width="6%"><code>~y</code></td><td width="23%">any</td><td width="50%">2-digit year</td><td width="23%"><code>date-year</code> within 50 years</td></tr> ++<tr><td width="6%"><code>~Y</code></td><td width="23%">char-numeric?</td><td width="50%">year</td><td width="23%"><code>date-year</code></td></tr> ++<tr><td width="6%"><code>~z</code></td><td width="23%">any</td><td width="50%">time zone</td><td width="23%"><code>date-zone-offset</code></td></tr> ++<tr class="srfi-plt-extension"><td width="6%"><code>~?</code></td><td width="23%">char-numeric?</td><td width="50%">2-digit or 4-digit year (PLT-specific extension)</td><td width="23%"><code>date-year</code></td></tr> ++<tr><td colspan="4"><hr width="100%" /></td></tr> ++<tr><th colspan="4">Table 2: <code>STRING->DATE</code> conversion specifiers</th></tr> ++<tr><td colspan="4"><hr width="100%" /></td></tr> ++</table> ++ ++<h2>Implementation</h2> + + This SRFI cannot be written in completely standard Scheme. In + particular, there must be some system-independent method of finding +@@ -553,34 +600,31 @@ the values for <code>CURRENT-TIME</code>. The GNU C function, + + <p>The difference between TAI and UTC is not determinate, and + implementations must provide some method for getting TAI. A procedure +-is provided in the accompany implmentation for reading the leap second ++is provided in the accompany implementation for reading the leap second + table provided by the Time Service of the US Naval Observatory +-(available at <a +-href="ftp://maia.usno.navy.mil/ser7/tai-utc.dat">ftp://maia.usno.navy.mil/ser7/tai-utc.dat</a>). +- +-<P>The accompanying implementation assumes <a +-href="http://srfi.schemers.org/srfi-6/">SRFI 6 Basic String Ports</a>. +-The accompanying implementation also assumes an <CODE>error</CODE> +-procedure. The accompanying implementation also assumes <a +-href="http://srfi.schemers.org/srfi-8/">SRFI 8 RECEIVE: Binding to ++(available at <a href="ftp://maia.usno.navy.mil/ser7/tai-utc.dat">ftp://maia.usno.navy.mil/ser7/tai-utc.dat</a>). ++ ++</p><p>The accompanying implementation assumes <a href="srfi-6.html">SRFI 6 Basic String Ports</a>. ++The accompanying implementation also assumes an <code>error</code> ++procedure. The accompanying implementation also assumes <a href="srfi-8.html">SRFI 8 RECEIVE: Binding to + multiple values</a>. which is easy to implement with the following + syntax: +- +-<CODE> +-<PRE> ++</p> ++<pre> + (define-syntax receive + (syntax-rules () + ((receive formals expression body ...) + (call-with-values (lambda () expression) + (lambda formals body ...))))) +-</PRE> +-</CODE> +- +-<p>Note that it contains TAI-UTC.DAT reader. ++</pre> + +-<P>The <a href="http://srfi.schemers.org/srfi-19/srfi-19.scm">accompanying ++<p> ++Note that it contains TAI-UTC.DAT reader. ++</p> ++<p> ++The <a href="https://srfi.schemers.org/srfi-19/srfi-19.scm">accompanying + implementation</a> is written in MzScheme. MzScheme provides the procedure +-<CODE>current-seconds</CODE>, which returns the number of seconds (UTC) ++<code>current-seconds</code>, which returns the number of seconds (UTC) + since 1970-01-01T00:00:00Z+00:00, and + <code>current-milliseconds</code>, which is a monotonic time + clock. Combining these provides an implementation of +@@ -590,46 +634,51 @@ UTC are resolved through a leap second table. According to the + International Earth Rotation Service, there will be no leap second in + December, 2000. Thus, the leap second table is guaranteed to be + correct through June, 2000. +- +-<p>Also, MzScheme (as of version 102, I believe) provides a method for ++</p> ++<p> ++Also, MzScheme (as of version 102, I believe) provides a method for + returning the current time zone offset, via its SECONDS->DATE and +-CURRENT-DATE procedures. +- +-<p>MzScheme's <code>DEFINE-STRUCT</code> was used to define the time +-and date objects. <a +-href="http://srfi.schemers.org/srfi-9/">SRFI 9</a>, Defining Record ++CURRENT-DATE procedures. ++</p> ++<p> ++MzScheme's <code>DEFINE-STRUCT</code> was used to define the time ++and date objects. <a href="srfi-9.html">SRFI 9</a>, Defining Record + Types, could be used instead. +- +-<p>Procedures meant to be used internally have names beginning with ++</p> ++<p> ++Procedures meant to be used internally have names beginning with + <code>TM:</code>. Locale-related constants and procedures have + <code>locale</code> in their name; if a 'locale' SRFI is ever written, + it might be good to use that code instead. ++</p> ++<p> ++From this, the rest of the implementation was built. ++</p> ++<p> ++There is also a <a href="https://srfi.schemers.org/srfi-19/srfi-19-test-suite.scm">test suite</a>. ++</p> + +-<p>From this, the rest of the implementation was built. +- +-<p>There is also a <a href="http://srfi.schemers.org/srfi-19/srfi-19-test-suite.scm">test suite</a>. +- +-<h1>Acknowledgements</h1> +- +-Claus Tøndering's<a href="http://www.tondering.dk/claus/calendar.html"> Frequently Asked Questions</a> about calendars was a very ++<h2>Acknowledgements</h2> ++<p> ++Claus ++Tøndering's<a href="http://www.tondering.dk/claus/calendar.html"> Frequently Asked Questions</a> about calendars was a very + useful resource. The implementation of Julian Day, Modified Julian +-Day, and Year Day comes from his FAQ. Markus Kuhn has a <a +-href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">useful +-description</a> of the <a +-href="http://www.iso.ch/markete/8601.pdf">ISO Standard 8601</a> for +-Date/Time notation; The W3 Consortium also has a <a +-href="http://www.w3.org/TR/NOTE-datetime">useful Note</a>. +- +-<p>Mike Sperber, Marc Feely, Dave Mason, and "Prfnoff" all made useful ++Day, and Year Day comes from his FAQ. Markus Kuhn has a <a href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">useful ++description</a> of the <a href="http://www.iso.ch/markete/8601.pdf">ISO Standard 8601</a> for ++Date/Time notation; The W3 Consortium also has a <a href="http://www.w3.org/TR/NOTE-datetime">useful Note</a>. ++</p> ++<p> ++Mike Sperber, Marc Feeley, Dave Mason, and "Prfnoff" all made useful + comments on previous versions of this draft. Thanks to Shriram + Krishnamurthi for his editing help. +- +-<p>The <code>DATE->STRING</code> procedure uses a format string, based on ++</p> ++<p> ++The <code>DATE->STRING</code> procedure uses a format string, based on + GNU C's <code>date</code> procedure, as well as <code>scsh</code>'s + <code>FORMAT-DATE</code> procedure. ++</p> + +- +-<H1>Copyright</H1> ++<h2>Copyright</h2> + + <p>Copyright (C) Neodesic Corporation (2000). All Rights Reserved.</p> + +@@ -656,11 +705,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +-<HR> ++<hr /> + +-<ADDRESS>Editor: <A href="mailto:srfi-editors@srfi.schemers.org">Shriram +-Krishnamurthi</A></ADDRESS> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Shriram ++Krishnamurthi</a></address> + Last +-modified by the author:<BR><CODE>(display (date->string (current-date 0) +-"~4"))</CODE>: 2004-03-15T02:21:15Z +-</BODY></HTML> ++modified by the author:<br /><code>(display (date->string (current-date 0) ++"~4"))</code>: 2017-05-05T21:42:17Z ++</body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html +index 18b6ba7..3c51824 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-2.html +@@ -1,38 +1,70 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> +- <head><title>SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* special form</title></head> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-2 ┃ ++┃ Commit: e929c1c50126d5a0c688a579b9f047700d60d735 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* special form</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> + + <body> +-<H1>Title</H1> +- +-SRFI-2: AND-LET*: an AND with local bindings, a guarded LET* special form +- +-<H1>Author</H1> +- +-Oleg Kiselyov +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion on this SRFI via <A HREF="http://srfi.schemers.org/srfi-2/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +- <LI>Received: 1998/12/28 +- <LI>Revised: 1999/02/09 +- <LI>Draft: 1998/12/28-1999/02/28 +- <LI>Final: 1999/03/01 +-</UL> +- +-<H1>Abstract</H1> +- +-<P>Like an ordinary AND, an AND-LET* special form evaluates its arguments -- ++<h1>SRFI 2: AND-LET*: an AND with local bindings, a guarded LET* special form</h1> ++ ++<p>by Oleg Kiselyov</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 2 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-2/srfi-2.html">https://srfi.schemers.org/srfi-2/srfi-2.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+2+at+srfi+dotschemers+dot+org">srfi-2@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-2">archive</a>.</p> ++<ul> ++ <li>Received: 1998-12-28 ++ </li><li>Revised: 1999-02-09 ++ </li><li>Draft: 1998-12-28--1999-02-28 ++ </li><li>Final: 1999-03-01 ++ </li><li>Revised to fix errata: ++ <ul> ++ <li>2020-06-08 (Fixed: Variables bound by AND-LET* needn't ++ be unique. This requirement was based on the mistaken ++ impression that LET* imposed that requirement, which it ++ doesn't. Also, updated link to sample implementation to ++ point to a more recent version by Oleg.)</li> ++ <li>2020-10-26 (Clarified what is meant by BODY in (and-let* ++ (CLAWS) BODY).)</li></ul></li> ++</ul> ++ ++<h2>Abstract</h2> ++ ++<p>Like an ordinary AND, an AND-LET* special form evaluates its arguments -- + expressions -- one after another in order, till the first one that + yields #f. Unlike AND, however, a non-#f result of one expression can + be bound to a fresh variable and used in the subsequent expressions. + AND-LET* is a cross-breed between LET* and AND. ++</p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + +-<P>In case of an ordinary AND formed of proper boolean expressions:<BR> +-(AND E1 E2 ...)<BR> ++<p>In case of an ordinary AND formed of proper boolean expressions:<br /> ++(AND E1 E2 ...)<br /> + expression E2, if it gets to be evaluated, knows that E1 has returned + non-#f. Moreover, E2 knows exactly what the result of E1 was -- #t -- + which E2 can use to its advantage. If E1 however is an extended +@@ -44,8 +76,8 @@ not an #f, and throws it away. If E2 needs it, it has to compute that + value anew. This proposed AND-LET* special form lets constituent + expressions get hold of the results of already evaluated expressions, + without re-doing their work. +- +-<P>AND-LET* can be thought of as a combination of LET* and AND, or a ++</p> ++<p>AND-LET* can be thought of as a combination of LET* and AND, or a + generalization of COND's send operator =>. An AND-LET* form can also be + considered a sequence of guarded expressions. In a regular program, + forms may produce results, bind them to variables and let other forms +@@ -53,21 +85,23 @@ use these results. AND-LET* differs in that it checks to make sure that + every produced result "makes sense" (that is, not an #f). The first + "failure" triggers the guard and aborts the rest of the sequence + (which presumably would not make any sense to execute anyway). +- ++</p> ++<p> + Examples: +-<PRE> ++</p> ++<pre> + (AND-LET* ((my-list (compute-list)) ((not (null? my-list)))) +- (do-something my-list)) ++ (do-something my-list)) + + (define (look-up key alist) + (and-let* ((x (assq key alist))) (cdr x))) + + (or +- (and-let* ((c (read-char)) +- ((not (eof-object? c)))) +- (string-set! some-str i c) +- (set! i (+ 1 i))) +- (begin (do-process-eof))) ++ (and-let* ((c (read-char)) ++ ((not (eof-object? c)))) ++ (string-set! some-str i c) ++ (set! i (+ 1 i))) ++ (begin (do-process-eof))) + + ; A more realistic example + ; Parse the 'timestamp' ::= 'token1' 'token2' +@@ -88,47 +122,48 @@ Examples: + (string-ref token2 2) (string-ref token2 3)))) + ((positive? timestamp))) + timestamp)) +-</PRE> +- +-<P> ++</pre> ++<p> + AND-LET* is also similar to an "anaphoric AND" LISP macro [Rob Warnock, + comp.lang.scheme, 26 Feb 1998 09:06:43 GMT, Message-ID: + 6d3bb3$3804h@fido.asd.sgi.com]. AND-LET* allows however more than one + intermediate result, each of which continues to be bound through the + rest of the form. ++</p> + ++<h2>Specification</h2> + +-<H1>Specification</H1> +- +-<H2><a name="and-let">Syntax and Informal Semantics</a></H2> ++<h3 id="and-let">Syntax and Informal Semantics</h3> + +-<PRE> ++<pre> + AND-LET* (CLAWS) BODY + + CLAWS ::= '() | (cons CLAW CLAWS) + CLAW ::= (VARIABLE EXPRESSION) | (EXPRESSION) | + BOUND-VARIABLE +-</PRE> ++</pre> + +-<UL> +-<LI>The CLAWS are evaluated in the strict left-to-right order +-<LI>For each CLAW, the EXPRESSION part is evaluated first (or BOUND-VARIABLE is looked up) +-<LI>If the result is #f, AND-LET* immediately returns #f +-<LI>Otherwise, if the CLAW is of the form (VARIABLE EXPRESSION) ++<ul> ++<li>The CLAWS are evaluated in the strict left-to-right order ++</li><li>For each CLAW, the EXPRESSION part is evaluated first (or BOUND-VARIABLE is looked up) ++</li><li>If the result is #f, AND-LET* immediately returns #f ++</li><li>Otherwise, if the CLAW is of the form (VARIABLE EXPRESSION) + the EXPRESSION's value is bound to a freshly made VARIABLE +-<LI>The VARIABLE is available for the rest of the CLAWS , and the BODY +-<LI>As usual, all VARIABLEs must be unique (like in let*) +-</UL> ++</li><li>The VARIABLE is available for the rest of the CLAWS , and the BODY ++</li><li><del>As usual, all VARIABLEs must be unique (like in let*)</del> ++</li><li>BODY is a body as in a LET* form.</li> ++ ++</ul> + +-<H2>Formal (Denotational) Semantics</H2> ++<h3>Formal (Denotational) Semantics</h3> + +-<PRE> ++<pre> + eval[ (AND-LET* (CLAW1 ...) BODY), env] = + eval_claw[ CLAW1, env ] andalso + eval[ (AND-LET* ( ...) BODY), ext_claw_env[CLAW1, env]] + + eval[ (AND-LET* (CLAW) ), env] = eval_claw[ CLAW, env ] +-eval[ (AND-LET* () FORM1 ...), env] = eval[ (BEGIN FORM1 ...), env ] ++eval[ (AND-LET* () FORM1 ...), env] = eval[ (LET* () FORM1 ...), env ] + eval[ (AND-LET* () ), env] = #t + + eval_claw[ BOUND-VARIABLE, env ] = +@@ -144,21 +179,15 @@ ext_claw_env[ (EXPRESSION), env ] = + ext_claw_env[ (VARIABLE EXPRESSION), env ] = + extend-env[ env-after-eval[ EXPRESSION, env ], + VARIABLE boundto eval[ EXPRESSION, env ]] +-</PRE> +- +-<H1>Implementation</H1> ++</pre> ++<h2>Implementation</h2> + +-<P>The full implementation plus the validation code are available <A href="http://srfi.schemers.org/srfi-2/vland-gambit.scm">here</A> (which is a copy of +-<A href="http://pobox.com/~oleg/ftp/Scheme/vland.scm"> +-http://pobox.com/~oleg/ftp/Scheme/vland.scm</A>). +- +-<P>This is an implementation of AND-LET* as a (Gambit) low-level macro that +-re-writes AND-LET* as a "tree" of AND and LET forms. A validation code is +-also presented, which verifies not only that everything works as +-expected, but also that AND-LET* finds syntax errors where expected. +- +-<H1>Copyright</H1> ++<p>A full sample implementation is available at <a class="eponymous" href="http://okmij.org/ftp/Scheme/lib/myenv-chez.scm">http://okmij.org/ftp/Scheme/lib/myenv-chez.scm</a>. The test suite is at <a class="eponymous" href="http://okmij.org/ftp/Scheme/tests/vland.scm">http://okmij.org/ftp/Scheme/tests/vland.scm</a>. ++</p> ++<h2>Copyright</h2> ++<p> + Copyright (C) Oleg Kiselyov (1998). All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -182,14 +211,13 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +-<address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Dave Mason</a></address> ++ <hr /> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Dave Mason</a></address> + <!-- Created: Mon Dec 28 13:49:00 PST 1998 --> +-<P> ++<p> + <!-- hhmts start --> +-Last modified: Wed Feb 6 17:21:57 MET 2002 ++Last modified: Sun Jan 28 13:40:28 MET 2007 + <!-- hhmts end --> +-</body> +-</html> +-<!-- <code><a href="mailto:oleg@pobox.com"><oleg@pobox.com></A></code>, <code><oleg@acm.org></code>, <code><oleg@computer.org></code>--> ++</p></body> ++</html><!-- <code><a href="mailto:oleg@okmij.org"><oleg@okmij.org></A></code>, <code><oleg@acm.org></code>, <code><oleg@computer.org></code>--> + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html +index 8ac31ca..ae2545c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-23.html +@@ -1,44 +1,57 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-23 ┃ ++┃ Commit: 79d424da4391152f12c0c8fad19f40dfe7fcd556 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 23: Error reporting mechanism</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 23: Error reporting mechanism</h1> + +-SRFI 23: Error reporting mechanism ++<p>by Stephan Houben</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 23 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-23/srfi-23.html">https://srfi.schemers.org/srfi-23/srfi-23.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Stephan Houben ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+23%20%20+at+srfi+dotschemers+dot+org">srfi-23 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-23">archive</a>.</p> ++<ul> ++<li>Draft: 2001-03-09--2001-06-09</li> ++<li>Revised: 2001-03-22 ++</li><li>Revised: 2001-04-26 ++</li></ul> + +-<H1>Status</H1> + +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-23/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-<P> +-<UL> +-<LI>Draft: 2001/03/09-2001/06/09</LI> +-<LI>Revised: 2001/03/22 +-<LI>Revised: 2001/04/26 +-</UL> +-</P> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + A mechanism is proposed to allow Scheme code to report errors and abort + execution. + The proposed mechanism is already implemented in several Scheme systems + and can be implemented, albeit imperfectly, in any R5RS conforming Scheme. + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p> + R5RS Scheme requires certain operations to signal an error when they fail. +@@ -46,14 +59,14 @@ R5RS Scheme requires certain operations to signal an error when they fail. + the error. + Moreover, R5RS encourages, but not requires, + implementations to signal an error in many more circumstances. +- ++</p> + <p> + However, there is no direct way for the Scheme application programmer to report +-an error that occurred in his or her own application. ++an error that occured in his or her own application. + This means that Scheme procedures created by applications or libraries are + in this respect not on equal footing with procedures provided by the + Scheme system. +- ++</p> + <p> + Many Scheme systems already provide a mechanism that allows application code + to report an error. At least the following implementations support +@@ -63,80 +76,96 @@ Of these implementations, the following have an error mechanism compatible + with this SRFI: Guile, MIT Scheme, PLT Scheme, RScheme, Scsh. + The implementation in SLIB has a different name than the + one proposed in this SRFI. +- ++</p> + <p> + To summarise, many implementations already have the error reporting + mechanism described in this SRFI and others are easily made compatible + with this SRFI. This shows that the proposed mechanism is considered useful + and that it is easy to implement in most major implementations. ++</p> + +-<H1>Specification</H1> ++<h2>Specification</h2> + + <p> + The following procedure should be provided: +-<p><a name="error"></a> ++</p> ++<p id="error"> + <code>(error</code> <reason><code> [<arg1> [<arg2> ...]])</code> ++</p> + <p> + The argument <reason> should be a string. + The procedure <code>error</code> will <em>signal an error</em>, + as described in R5RS, and it will report the message <reason> +-and the objects <arg1>, <arg2>, .... ++and the objects <arg1>, <arg2>, .... + What exactly constitutes "signalling" and "reporting" is not prescribed, because of the large variation in Scheme systems. So it is left to the implementor + to do something reasonable. To that end, a few examples of possible behaviour + are given. ++</p> + <ol> + <li> + Display <reason> and <arg1>... on the screen and terminate + the Scheme program. (This might be suitable for a Scheme system + implemented as a batch compiler.) +- <li> ++ </li> ++ <li> + Display <reason> and <arg1>... on the screen and + go back to the read-evaluate-print loop. (This might be suitable for + an interactive implementation). ++ </li> + <li> + In the case of a multi-threaded system: terminate the current + thread, but do not terminate the other threads. Possibly make the + arguments to <code>error</code> available to other threads in some + way. See the <code>thread-join!</code> mechanism in SRFI-18 on + how this could be done. ++ </li> + <li> + Package <reason> and <arg1>... up into an error object + and pass this error object to an exception handler. The default + exception handler then might do something as described in points 1 to 3. ++ </li> + <li> + In the case of a Scheme system that runs completely unattended + and that has no way to notify a human, the only reasonable + course of action might be to do nothing at all. However, this should + be considered a last resort. Clearly, if all implementors would choose + this strategy, this SRFI would not be very useful. +-</ol> ++ </li> ++</ol> ++<p> + An implementation might report more information than just + <reason> and <arg1>... . For instance, it might report the procedure name in which + the error occurred or even print a stack trace. + However, this will require additional support in the Scheme implementation. ++</p> + ++<h2>Why <code>error</code> is a procedure</h2> + +-<H1>Why <code>error</code> is a procedure</H1> +- ++<p> + It is conceivable to allow <code>error</code> to be a special form, + such as a macro, rather than a procedure. This might make providing + information such as the source code location easier. This possibility + has been considered, but rejected, for two reasons. ++</p> + <ol> + <li> + Since <code>error</code> accepts a variable number of arguments, + it could occasionally be useful to use <code>apply</code> to call + <code>error</code>. However, this is not possible if <code>error</code> + was allowed to be a special form. ++ </li> + <li> + Since <code>error</code> is currently a procedure in all Scheme + implementations mentioned above, it doesn't seem all that + worthwhile to allow it to be a special form. ++ </li> + </ol> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + ++<p> + An implementation that works in almost any R5RS Scheme is the following: ++</p> + <pre> + (define (error reason . args) + (display "Error: ") +@@ -148,36 +177,42 @@ An implementation that works in almost any R5RS Scheme is the following: + (newline) + (scheme-report-environment -1)) ;; we hope that this will signal an error + </pre> ++<p> + This implementation has a flaw, + namely, in many implementations this + will actually print 2 messages. ++</p> + <ol> + <li> The message <code>message</code>, followed by <code>objs</code>, and +- <li> A message about <code>scheme-report-environment</code> getting an invalid argument. +-</ol> ++ </li> ++ <li> A message about <code>scheme-report-environment</code> getting an invalid argument. ++ </li> ++</ol> ++<p> + This might be confusing to the user. +- ++</p> + <p> + The <a href="http://www.swiss.ai.mit.edu/~jaffer/SLIB.html">SLIB</a> procedure <code>slib:error</code> works like the <code>error</code> + procedure described in this document. + Thus, when SLIB is loaded, <code>error</code> can be defined as: ++</p> + <pre> + (define error slib:error) + </pre> +- + <p> +-If <a href="http://srfi.schemers.org/srfi-18/">SRFI 18</a> is supported, it is allowed ++If <a href="https://srfi.schemers.org/srfi-18/">SRFI 18</a> is supported, it is allowed + (but not required) to implement <code>error</code> in + terms of the exception mechanism of SRFI 18. ++</p> + <pre> + (define (error reason . args) + (raise (make-error-exception reason args))) + </pre> ++<p> + Here, <code>make-error-exception</code> is implementation dependent. +- +-<H1>Copyright</H1> ++</p> ++<h2>Copyright</h2> + <p>Copyright (C) <a href="mailto:stephanh@win.tue.nl">Stephan Houben</a> (2001). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -200,13 +235,11 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> +- +- <hr> +- <address>Editor: <a +- href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Thu Mar 8 15:33:07 CET 2001 --> + <!-- hhmts start --> +-Last modified: Mon Feb 4 14:46:29 MET 2002 ++Last modified: Sun Jan 28 13:40:28 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html +index 4d81d03..000adb1 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-25.html +@@ -1,36 +1,50 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-25 ┃ ++┃ Commit: 70c44ee28ebe6c13a5a91c6d7c2f8333828fdb66 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 25: Multi-dimensional Array Primitives</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 25: Multi-dimensional Array Primitives</h1> + +-SRFI 25: Multi-dimensional Array Primitives ++<p>by Jussi Piitulainen</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 25 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-25/srfi-25.html">https://srfi.schemers.org/srfi-25/srfi-25.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Jussi Piitulainen ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+25%20%20+at+srfi+dotschemers+dot+org">srfi-25 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-25">archive</a>.</p> ++<ul> ++<li>Draft: 2001-11-12--2002-01-11 </li> ++<li>Revised: 2002-02-03</li> ++<li>Final: 2002-05-21</li> ++</ul> + +-<H1>Status</H1> + +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-25/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-<P> +-<UL> +-<LI>Draft: 2001/11/12-2002/01/11 </LI> +-<LI>Revised: 2002/02/03</LI> +-<LI>Final: 2002/05/21</LI> +-</UL> +-</P> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + <p> + A core set of procedures for creating and manipulating heterogeneous +@@ -45,7 +59,7 @@ The specification is based on an original contribution by Alan Bawden + in 1993. + </p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p> + The proposed arrays encourage a natural declarative programming +@@ -108,7 +122,7 @@ It is not required that vectors not be arrays. It is not required that + they be, either. + </p> + +-<H1>Specification</H1> ++<h2>Specification</h2> + + <p> + Arrays are heterogeneous data structures whose elements are indexed by +@@ -141,8 +155,8 @@ alternately the lower and upper bounds for the dimensions of an array. + The following ten procedures should be implemented. + </p> + +-<p><a name="array-p"></a> +-<code>(array? <var>obj</var>)</code><br> ++<p id="array-p"> ++<code>(array? <var>obj</var>)</code><br /> + + Returns <samp>#t</samp> if <var>obj</var> is an array, otherwise + returns <samp>#f</samp>. +@@ -150,14 +164,14 @@ returns <samp>#f</samp>. + + <p> + Note: there is no reasonable way to implement this procedure +-accurately in R5RS; <a href="http://srfi.schemers.org/srfi-9/">SRFI ++accurately in R5RS; <a href="srfi-9.html">SRFI + 9</a> (Defining Record Types) specifies a way, and many Scheme + implementations provide something similar. + </p> + +-<p><a name="make-array"></a> +-<code>(make-array <var>shape</var>)</code><br> +-<code>(make-array <var>shape</var> <var>obj</var>)</code><br> ++<p id="make-array"> ++<code>(make-array <var>shape</var>)</code><br /> ++<code>(make-array <var>shape</var> <var>obj</var>)</code><br /> + + Returns a newly allocated array whose shape is given by + <var>shape</var>. If <var>obj</var> is provided, then each element is +@@ -166,8 +180,8 @@ unspecified. The array does not retain a dependence to + <var>shape</var>. + </p> + +-<p><a name="shape"></a> +-<code>(shape <var>bound ...</var>)</code><br> ++<p id="shape"> ++<code>(shape <var>bound ...</var>)</code><br /> + + Returns a shape. The sequence <var>bound ...</var> must consist of an + even number of exact integers that are pairwise not decreasing. Each +@@ -190,42 +204,42 @@ corresponding upper bound, where <var>k</var> satisfies + <code>(< <var>k</var> <var>d</var>)</code>. + </p> + +-<p><a name="array"></a> +-<code>(array <var>shape</var> <var>obj ...</var>)</code><br> ++<p id="array"> ++<code>(array <var>shape</var> <var>obj ...</var>)</code><br /> + + Returns a new array whose shape is given by <var>shape</var> and the + initial contents of the elements are <var>obj ...</var> in row major + order. The array does not retain a dependence to <var>shape</var>. + </p> + +-<p><a name="array-rank"></a> +-<code>(array-rank <var>array</var>)</code><br> ++<p id="array-rank"> ++<code>(array-rank <var>array</var>)</code><br /> + + Returns the number of dimensions of <var>array</var>. ++</p> + <pre> + (array-rank + (make-array (shape 1 2 3 4))) + </pre> +- + <p> + Returns <samp>2</samp>. + </p> + +-<p><a name="array-start"></a> +-<code>(array-start <var>array</var> <var>k</var>)</code><br> ++<p id="array-start"> ++<code>(array-start <var>array</var> <var>k</var>)</code><br /> + + Returns the lower bound for the index along dimension <var>k</var>. + </p> + +-<p><a name="array-end"></a> +-<code>(array-end <var>array</var> <var>k</var>)</code><br> ++<p id="array-end"> ++<code>(array-end <var>array</var> <var>k</var>)</code><br /> + + Returns the upper bound for the index along dimension <var>k</var>. + </p> + + <!-- + <p> +-<code>(array-shape <var>array</var>)</code><br> ++<code>(array-shape <var>array</var>)</code><br /> + + Returns a newly allocated shape of <var>array</var>. + </p> +@@ -246,9 +260,9 @@ from any array. + </p> + --> + +-<p><a name="array-ref"></a> +-<code>(array-ref <var>array</var> <var>k ...</var>)</code><br> +-<code>(array-ref <var>array</var> <var>index</var>)</code><br> ++<p id="array-ref"> ++<code>(array-ref <var>array</var> <var>k ...</var>)</code><br /> ++<code>(array-ref <var>array</var> <var>index</var>)</code><br /> + + Returns the contents of the element of <var>array</var> at index + <var>k ...</var>. The sequence <var>k ...</var> must be a valid index +@@ -280,30 +294,29 @@ Returns <samp>cuatro</samp>. + Returns <samp>(3 1 4)</samp>. + </p> + +-<p><a name="array-set!"></a> +-<code>(array-set! <var>array</var> <var>k ...</var> <var>obj</var>)</code><br> +-<code>(array-set! <var>array</var> <var>index</var> <var>obj</var>)</code><br> ++<p id="array-set!"> ++<code>(array-set! <var>array</var> <var>k ...</var> <var>obj</var>)</code><br /> ++<code>(array-set! <var>array</var> <var>index</var> <var>obj</var>)</code><br /> + + Stores <var>obj</var> in the element of <var>array</var> at index + <var>k ...</var>. Returns an unspecified value. The sequence <var>k + ...</var> must be a valid index to <var>array</var>. In the second + form, <var>index</var> must be either a vector or a 0-based + 1-dimensional array containing <var>k ...</var>. +- ++</p> + <pre> + (let ((a (make-array + (shape 4 5 4 5 4 5)))) + (array-set! a 4 4 4 'huuhkaja) + (array-ref a 4 4 4)) + </pre> +- + <p> + Returns <samp>huuhkaja</samp>. + </p> + +-<p><a name="share-array"></a> ++<p id="share-array"> + <code>(share-array <var>array</var> <var>shape</var> <var>proc</var>)</code> +-<br> ++<br /> + + Returns a new array of shape <var>shape</var> that shares elements of + <var>array</var> through <var>proc</var>. The procedure +@@ -351,7 +364,7 @@ This document does not specify when arrays are <code>equal?</code>. + (Indeed, R5RS <code>equal?</code> will do the wrong thing.) + </p> + +-<h1>Examples</h1> ++<h2>Examples</h2> + + <p> + The reference implementation comes with a number of files that +@@ -361,36 +374,33 @@ in <em>testing</em> an implementation; that is their origin). + + <ol> + +-<li> A library <a href="http://srfi.schemers.org/srfi-25/arlib.scm">arlib.scm</a> that contains, among ++<li> A library <a href="https://srfi.schemers.org/srfi-25/arlib.scm">arlib.scm</a> that contains, among + several other things, <code>tabulate-array</code> for a more + useful initialization of a new array, an + <code>array-equal?</code>, and a <code>transpose</code> that can + permute the dimensions of an array any which way. + +-<li> A test suite <a href="http://srfi.schemers.org/srfi-25/test.scm">test.scm</a> for <em>array</em>, +- and another test suite <a href="http://srfi.schemers.org/srfi-25/list.scm">list.scm</a> for ++</li><li> A test suite <a href="https://srfi.schemers.org/srfi-25/test.scm">test.scm</a> for <em>array</em>, ++ and another test suite <a href="https://srfi.schemers.org/srfi-25/list.scm">list.scm</a> for + <em>arlib</em>. + +-<li> A rudimentary display procedure <code>(play array)</code> in <a +- href="http://srfi.schemers.org/srfi-25/play.scm">play.scm</a>, for playing around with the system. ++</li><li> A rudimentary display procedure <code>(play array)</code> in <a href="https://srfi.schemers.org/srfi-25/play.scm">play.scm</a>, for playing around with the system. + +-</ol> ++</li></ol> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + + <p> + A portable reference implementation is provided. It uses a minimal +-error reporting mechanism that conforms to <a +-href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> (Error reporting ++error reporting mechanism that conforms to <a href="srfi-23.html">SRFI 23</a> (Error reporting + mechanism). Type disjointness requires support from the host +-implementation, such as support for <a +-href="http://srfi.schemers.org/srfi-9/">SRFI 9</a> (Defining Record ++implementation, such as support for <a href="srfi-9.html">SRFI 9</a> (Defining Record + Types). All names not defined in this proposal are in the prefix + "<code>array:</code>", which serves as a module system. + </p> + + <p> +-You can get <a href="http://srfi.schemers.org/srfi-25/srfi-25-reference.scm">source for the reference ++You can get <a href="https://srfi.schemers.org/srfi-25/srfi-25-reference.scm">source for the reference + implementation</a> as a single file and stop reading. But there are + variations. This single file represents arrays as procedures (so the + type predicate is very approximate); it represents index mapping as +@@ -410,18 +420,18 @@ consists of the following parts, each in its own file. + type disjointness, or portable as procedures, in a file + <em>as-*.scm</em>, and + +-<li> <dfn>indexing operations</dfn> to match the type, in a file ++</li><li> <dfn>indexing operations</dfn> to match the type, in a file + <em>ix-*.scm</em>, and + +-<li> an <dfn>affine recogniser</dfn> of one of three types, optimised ++</li><li> an <dfn>affine recogniser</dfn> of one of three types, optimised + up to some number of dimensions, in a file <em>op-*.scm</em>, and + +-<li> the main source file <a href="http://srfi.schemers.org/srfi-25/array.scm">array.scm</a>. ++</li><li> the main source file <a href="https://srfi.schemers.org/srfi-25/array.scm">array.scm</a>. + +-</ol> ++</li></ol> + + <p> +-Affine recognisers are made by a program <a href="http://srfi.schemers.org/srfi-25/opt.scm">opt.scm</a> ++Affine recognisers are made by a program <a href="https://srfi.schemers.org/srfi-25/opt.scm">opt.scm</a> + but one of each type is also available here, optimized for 0, 1, 2 and + 3 dimensions. Choose one type: pick a recogniser with matching index + procedures; load <tt>as-</tt>, <tt>ix-</tt> and <tt>op-</tt> and +@@ -430,36 +440,34 @@ procedures; load <tt>as-</tt>, <tt>ix-</tt> and <tt>op-</tt> and + + <ol> + +-<li> In the <a href="http://srfi.schemers.org/srfi-25/op-mbda.scm">mbda</a> type representation, index ++<li> In the <a href="https://srfi.schemers.org/srfi-25/op-mbda.scm">mbda</a> type representation, index + mappings are procedures that accept an optional argument. The +- matching <a href="http://srfi.schemers.org/srfi-25/ix-mbda.scm">access procedures</a> apply the ++ matching <a href="https://srfi.schemers.org/srfi-25/ix-mbda.scm">access procedures</a> apply the + mapping to the arguments of <code>array-ref</code> and + <code>array-set!</code>. + +-<li> In the <a href="http://srfi.schemers.org/srfi-25/op-tter.scm">tter</a> type representation, index ++</li><li> In the <a href="https://srfi.schemers.org/srfi-25/op-tter.scm">tter</a> type representation, index + mappings are pairs of procedures: one takes exactly the indices, +- the other takes indices and an object. The matching <a +- href="http://srfi.schemers.org/srfi-25/ix-tter.scm">access procedures</a> apply the first ++ the other takes indices and an object. The matching <a href="https://srfi.schemers.org/srfi-25/ix-tter.scm">access procedures</a> apply the first + procedure to the argumets of <code>array-ref</code> and the + second procedure to the arguments of <code>array-set!</code>. + +-<li> In <a href="http://srfi.schemers.org/srfi-25/op-ctor.scm">ctor</a> representation, index mappings +- are coefficient vectors. The <a href="http://srfi.schemers.org/srfi-25/ix-ctor.scm">access ++</li><li> In <a href="https://srfi.schemers.org/srfi-25/op-ctor.scm">ctor</a> representation, index mappings ++ are coefficient vectors. The <a href="https://srfi.schemers.org/srfi-25/ix-ctor.scm">access + procedures</a> compute the sum of products of coefficients and + indexes in a loop on the list. + +-</ol> ++</li></ol> + + <p> +-Record implementations are available <a href="http://srfi.schemers.org/srfi-25/as-procedure.scm">for +-generic Scheme</a> (arrays are not disjoint from procedures), <a +-href="http://srfi.schemers.org/srfi-25/as-srfi-9-record.scm">for SRFI 9</a> (Defining Record Types) +-(<em>not tested</em>), and <a href="http://srfi.schemers.org/srfi-25/as-plt-struct.scm">for PLT ++Record implementations are available <a href="https://srfi.schemers.org/srfi-25/as-procedure.scm">for ++generic Scheme</a> (arrays are not disjoint from procedures), <a href="https://srfi.schemers.org/srfi-25/as-srfi-9-record.scm">for SRFI 9</a> (Defining Record Types) ++(<em>not tested</em>), and <a href="https://srfi.schemers.org/srfi-25/as-plt-struct.scm">for PLT + Scheme</a> (arrays belong to a struct type). + </p> + + <p> +-With the three files from above, the <a href="http://srfi.schemers.org/srfi-25/array.scm">main source ++With the three files from above, the <a href="https://srfi.schemers.org/srfi-25/array.scm">main source + file</a> should work in any Scheme implementation without need of + modification. + </p> +@@ -471,7 +479,7 @@ code. (Sharing uses a check that is exponential in the number of + dimensions. It is disabled above a threshold rank.) + </p> + +-<h1>Acknowledgements</h1> ++<h2>Acknowledgements</h2> + + <p> + The original concept comes from a message to the Usenet newsgroup +@@ -490,11 +498,10 @@ wording, hidden shapes, and two kinds of index objects. + + <p> + The exact title of the proposal comes from a <a href="http://zurich.ai.mit.edu/pipermail/rrrs-authors/1998-May/002349.html">message titled "a process that might work"</a> by William D. Clinger to the <tt>rrrs-authors</tt> +-mailing list in 1998. That appears to be a part of the past of the <a +-href="http://srfi.schemers.org">SRFI process</a>. ++mailing list in 1998. That appears to be a part of the past of the <a href="https://srfi.schemers.org">SRFI process</a>. + </p> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Jussi Piitulainen (2001). All Rights Reserved.</p> + + <p> +@@ -520,12 +527,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a +- href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Tue May 28 18:46:09 MST 2002 ++Last modified: Sun Jan 28 13:40:29 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html +index a6cf487..0d6d83e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-26.html +@@ -1,39 +1,54 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-26 ┃ ++┃ Commit: 0b373428f9528198fd6691f9c842fea8e2dcf7df ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 26: Notation for Specializing Parameters without Currying</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 26: Notation for Specializing Parameters without Currying</h1> + +-SRFI 26: Notation for Specializing Parameters without Currying ++<p>by Sebastian Egner</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 26 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-26/srfi-26.html">https://srfi.schemers.org/srfi-26/srfi-26.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Sebastian Egner ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+26+at+srfi+dotschemers+dot+org">srfi-26@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-26">archive</a>.</p> ++<ul> ++<li>Draft: 2002-02-06--2002-04-06 </li> ++<li>Revised: 2002-02-15</li> ++<li>Revised: 2002-02-28</li> ++<li>Revised: 2002-06-04</li> ++<li>Revised: 2002-06-06</li> ++<li>Final: 2002-06-14</li> ++</ul> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +-<UL> +-<LI>Draft: 2002/02/06-2002/04/06 </LI> +-<LI>Revised: 2002/02/15</LI> +-<LI>Revised: 2002/02/28</LI> +-<LI>Revised: 2002/06/04</LI> +-<LI>Revised: 2002/06/06</LI> +-<LI>Final: 2002/06/14</LI> +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + ++<p> + When programming in functional style, + it is frequently necessary to specialize some of the + parameters of a multi-parameter procedure. +@@ -41,40 +56,41 @@ For example, from the binary operation <code>cons</code> + one might want to obtain the unary operation + <code>(lambda (x) (cons 1 x))</code>. + This specialization of parameters is also known as +-"partial application", "operator section" or "projection".<p> +- ++"partial application", "operator section" or "projection". ++</p> ++<p> + The mechanism proposed here allows to write this sort + of specialization in a simple and compact way. +-The mechanism is best explained by a few examples:<p> +- +-<TABLE> +-<TR> +-<TD><code>(cut cons (+ a 1) <>)</code> +-<TD>is the same as +-<TD><code>(lambda (x2) (cons (+ a 1) x2))</code> +-</TR> +-<TR> +-<TD><code>(cut list 1 <> 3 <> 5)</code> +-<TD>is the same as +-<TD><code>(lambda (x2 x4) (list 1 x2 3 x4 5))</code> +-</TR> +-<TR> +-<TD><code>(cut list)</code> +-<TD>is the same as +-<TD><code>(lambda () (list))</code> +-</TR> +-<TR> +-<TD><code>(cut list 1 <> 3 <...>)</code> +-<TD>is the same as +-<TD><code>(lambda (x2 . xs) (apply list 1 x2 3 xs))</code> +-</TR> +-<TR> +-<TD><code>(cut <> a b)</code> +-<TD>is the same as +-<TD><code>(lambda (f) (f a b))</code> +-</TR> +-</TABLE><p> +- ++The mechanism is best explained by a few examples: ++</p> ++<table> ++<tr> ++ <td><code>(cut cons (+ a 1) <>)</code></td> ++ <td>is the same as</td> ++ <td><code>(lambda (x2) (cons (+ a 1) x2))</code></td> ++</tr> ++<tr> ++ <td><code>(cut list 1 <> 3 <> 5)</code></td> ++ <td>is the same as</td> ++ <td><code>(lambda (x2 x4) (list 1 x2 3 x4 5))</code></td> ++</tr> ++<tr> ++ <td><code>(cut list)</code></td> ++ <td>is the same as</td> ++ <td><code>(lambda () (list))</code></td> ++</tr> ++<tr> ++ <td><code>(cut list 1 <> 3 <...>)</code></td> ++ <td>is the same as</td> ++ <td><code>(lambda (x2 . xs) (apply list 1 x2 3 xs))</code></td> ++</tr> ++<tr> ++ <td><code>(cut <> a b)</code></td> ++ <td>is the same as</td> ++ <td><code>(lambda (f) (f a b))</code></td> ++</tr> ++</table> ++<p> + As you see, the macro <code>cut</code> specializes some of the + parameters of its first argument. + The parameters that are to show up as formal +@@ -83,27 +99,29 @@ pronouced as "slot". In addition, the symbol <code><...></code>, + pronounced as "rest-slot", matches all residual arguments of a variable + argument procedure. + As you can see from the last example above, the first argument can also +-be a slot, as one should expect in Scheme.<p> +- ++be a slot, as one should expect in Scheme. ++</p> ++<p> + In addition to <code>cut</code>, there is a variant called <code>cute</code> + (a mnemonic for "<code>cut</code> with evaluated non-slots") which evaluates + the non-slot expressions at the time the procedure is specialized, not at + the time the specialized procedure is called. +-For example,<p> +- +-<TABLE> +-<TR> +-<TD><code>(cute cons (+ a 1) <>)</code> +-<TD>is the same as +-<TD><code>(let ((a1 (+ a 1))) (lambda (x2) (cons a1 x2)))</code> +-</TR> +-</TABLE><p> +- ++For example, ++</p> ++<table> ++<tr> ++ <td><code>(cute cons (+ a 1) <>)</code></td> ++ <td>is the same as</td> ++ <td><code>(let ((a1 (+ a 1))) (lambda (x2) (cons a1 x2)))</code></td> ++</tr> ++</table> ++<p> + As you see from comparing this example with the first example above, + the <code>cute</code>-variant will evaluate <code>(+ a 1)</code> + once, while the <code>cut</code>-variant will evaluate it during +-every invokation of the resulting procedure.<p> +- ++every invokation of the resulting procedure. ++</p> ++<p> + The mechanism proposed in this SRFI allows specializing any subset + of the variables of a procedure. + The result can be of fixed arity or of variable arity. +@@ -111,11 +129,13 @@ The mechanism does not allow permutation, omission, duplication + or any other processing of the arguments; + for this it is necessary to write to use a different + mechanism such as <code>lambda</code>. ++</p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + ++<p> + A particularly elegant way to deal with specialization is known +-as <em>currying</em> (Schönfinkel 1924, Curry 1958). ++as <em>currying</em> (Schönfinkel 1924, Curry 1958). + The idea of currying is to reduce multi-argument functions to + single-argument functions by regarding an <i>n</i>-ary + function as a unary function mapping its first argument into +@@ -123,8 +143,9 @@ an (<i>n</i>-1)-ary function (which is curried in turn). + This point of view, apart from its theoretical elegance, + allows an extremely compact notation for specializing the + first argument of a function. +-In the first example, one could simply write <code>(cons 1)</code>.<p> +- ++In the first example, one could simply write <code>(cons 1)</code>. ++</p> ++<p> + Yet, Scheme is not a curried language---the + number of arguments passed to a procedure must match + the number of its parameters at all times. +@@ -135,73 +156,91 @@ and invent some irrelevant identifiers for its + formal variables (<code>x</code> in the example). + For this reason, the mechanism proposed in this SRFI + provides a simple and compact notation for specializing +-any subset of the parameters of a procedure.<p> +- +-Note: <em>The mechanism proposed here is not currying!</em><p> +- ++any subset of the parameters of a procedure. ++</p> ++<p> ++Note: <em>The mechanism proposed here is not currying!</em> ++</p> ++<p> + The purpose of the mechanism proposed here is to make the benefits + of currying available within the programming language Scheme. + There are two primary benefits of currying in practice: + Higher-order types are substantially simplified and + there is a simple notation for specializing parameters. + The type aspect is irrelevant as Scheme has latent typing. +-The specialization aspect is largly covered with this SRFI.<p> +- ++The specialization aspect is largly covered with this SRFI. ++</p> ++<p> + Here are a few more examples for illustration: ++</p> ++<table> ++<tr> ++ <td><code>(map (cut * 2 <>) '(1 2 3 4))</code></td> ++</tr> ++<tr> ++ <td><code>(map (cut vector-set! x <> 0) indices)</code></td> ++</tr> ++<tr> ++ <td><code>(for-each (cut write <> port) exprs)</code></td> ++</tr> ++<tr> ++ <td><code>(map (cut <> x y z) (list min max))</code></td> ++</tr> ++<tr> ++ <td><code>(for-each (cut <>) thunks)</code></td> ++</tr> ++</table> ++ ++<h2>Specification</h2> + +-<TABLE> +-<TR> +-<TD><code>(map (cut * 2 <>) '(1 2 3 4))</code> +-</TR> +-<TR> +-<TD><code>(map (cut vector-set! x <> 0) indices)</code> +-</TR> +-<TR> +-<TD><code>(for-each (cut write <> port) exprs)</code> +-</TR> +-<TR> +-<TD><code>(map (cut <> x y z) (list min max))</code> +-</TR> +-<TR> +-<TD><code>(for-each (cut <>) thunks)</code> +-</TR> +-</TABLE> +- +-<H1>Specification</H1> +- +-<a name="cut"></a><a name="cute"></a> ++<p> + The formal syntax of a specialized expression, in the style of the +-<a href="http://www.schemers.org/Documents/Standards/R5RS/"><I>Revised^5 Report on the Algorithmic Language Scheme</I></a>:<p> +- +-<TABLE> +-<TR> +-<TD><a name="cut"></a><a name="cute"></a><code><cut-expression></code> +-<TD><code>--></code> +-<TD><TD><code>(cut <slot-or-expr> <slot-or-expr>*)</code> +-<TD> +-</TR> +-<TR> +-<TD><TD><TD>|<TD><code>(cut <slot-or-expr> <slot-or-expr>* <...>)</code> +-<TD>; with "rest-slot" +-</TR> +-<TR> +-<TD><TD><TD>|<TD><code>(cute <slot-or-expr> <slot-or-expr>*)</code> +-<TD>; evaluate non-slots at specialization time +-</TR> +-<TR> +-<TD><TD><TD>|<TD><code>(cute <slot-or-expr> <slot-or-expr>* <...>)</code> +-<TD>; with "rest-slot" +-</TR> +-<TR> +-<TD><code><slot-or-expr></code> +-<TD><code>--></code> +-<TD><TD><code><></code><TD>; a "slot" +-</TR> +-<TR> +-<TD><TD><TD>|<TD> <code><expression></code><TD>; a "non-slot expression" +-</TR> +-</TABLE><p> +- ++<a href="http://www.schemers.org/Documents/Standards/R5RS/"><i>Revised^5 Report on the Algorithmic Language Scheme</i></a>:</p><p> ++</p> ++<table> ++<tr id="cut"> ++ <td><code><cut-expression></code></td> ++ <td><code>--></code></td> ++ <td></td> ++ <td><code>(cut <slot-or-expr> <slot-or-expr>*)</code></td> ++ <td></td> ++</tr> ++<tr> ++ <td></td> ++ <td></td> ++ <td>|</td> ++ <td><code>(cut <slot-or-expr> <slot-or-expr>* <...>)</code></td> ++ <td>; with "rest-slot"</td> ++</tr> ++<tr id="cute"> ++ <td></td> ++ <td></td> ++ <td>|</td> ++ <td><code>(cute <slot-or-expr> <slot-or-expr>*)</code></td> ++ <td>; evaluate non-slots at specialization time</td> ++</tr> ++<tr> ++ <td></td> ++ <td></td> ++ <td>|</td> ++ <td><code>(cute <slot-or-expr> <slot-or-expr>* <...>)</code></td> ++ <td>; with "rest-slot"</td> ++</tr> ++<tr> ++ <td><code><slot-or-expr></code></td> ++ <td><code>--></code></td> ++ <td></td> ++ <td><code><></code></td> ++ <td>; a "slot"</td> ++</tr> ++<tr> ++ <td></td> ++ <td></td> ++ <td>|</td> ++ <td> <code><expression></code></td><td>; a "non-slot expression"</td> ++</tr> ++</table> ++<p> + The macro <code>cut</code> transforms a <code><cut-expression></code> + into a <code><lambda expression></code> with as many formal variables + as there are slots in the list <code><slot-or-expr>*</code>. +@@ -210,18 +249,21 @@ the first <code><slot-or-expr></code> with arguments from + <code><slot-or-expr>*</code> in the order they appear. + In case there is a rest-slot symbol, the resulting procedure is also of + variable arity, and the body calls the first <code><slot-or-expr></code> +-with all arguments provided to the actual call of the specialized procedure.<p> +- ++with all arguments provided to the actual call of the specialized procedure. ++</p> ++<p> + The macro <code>cute</code> is similar to the macro <code>cut</code>, + except that it first binds new variables to the result of evaluating + the non-slot expressions (in an unspecific order) and then substituting + the variables for the non-slot expressions. + In effect, <code>cut</code> evaluates non-slot expressions at the time + the resulting procedure is called, whereas <code>cute</code> evaluates +-the non-slot expressions at the time the procedure is constructed.<p> ++the non-slot expressions at the time the procedure is constructed. ++</p> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + ++<p> + The reference implementation defines the two macros + <code>cut</code> and <code>cute</code> using macro + mechanism of R5RS. +@@ -232,24 +274,26 @@ As macros in R5RS are hygienic and referentially transparent, + the macro mechanism makes sure the names of the newly + introduced formal variables are unique and do not clash. + The template <code>(param ... slot)</code>, see +-<a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.1.5">Sect. 7.1.5. of R5RS</a>, ++<a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%25_sec_7.1.5">Sect. 7.1.5. of R5RS</a>, + allows to preserve the order of arguments---which would get + reversed otherwise. +- ++</p> ++<p> + The reference implementation has been written by +-Al Petrofsky. It can be found <a href="http://srfi.schemers.org/srfi-26/cut.scm">here</a>.<p> +- ++Al Petrofsky. It can be found <a href="https://srfi.schemers.org/srfi-26/cut.scm">here</a>. ++</p> ++<p> + Finally, there is a small collection of +-<a href="http://srfi.schemers.org/srfi-26/check.scm">confidence tests</a>. ++<a href="https://srfi.schemers.org/srfi-26/check.scm">confidence tests</a>. + It checks some special cases of the mechanism defined + in this SRFI and signals an error in case something is wrong. + Passing the tests does not mean a correct implementation. ++</p> + ++<h2>Design Rationale</h2> + +-<H1>Design Rationale</H1> +- +-<H3>Why not real currying/uncurrying?</H3> +- ++<h3>Why not real currying/uncurrying?</h3> ++<p> + It is possible in Scheme to implement a macro turning a multi-argument + procedure into a nesting of single-argument procedures and back. + These operations are usually called "curry" and "uncurry" in +@@ -261,11 +305,12 @@ if you apply it in the sequence "curry, specialize some arguments, + and uncurry again"---which is exactly the purpose of the macro + <code>cut</code> specified in this document. + The primary relevance of currying/uncurrying in Scheme is to +-teach concepts of combinatory logic.<p> +- +-<H3>Why not a more general mechanism, also allowing permutation, +-omission and duplication of arguments?</H3> ++teach concepts of combinatory logic. ++</p> + ++<h3>Why not a more general mechanism, also allowing permutation, ++omission and duplication of arguments?</h3> ++<p> + The reason is that I, the author of this SRFI, consider more general + mechanisms too dangerous to mix them with the mechanism proposed here. + In particular, as soon as parameters are being rearranged it +@@ -273,13 +318,14 @@ is usually necessary to be aware of the meaning of the parameters; + unnamed variables can be quite harmful then. + The mechanism proposed here is designed to prevent this. + Please refer to the discussion threads +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00018.html">"OK, how about...,"</a> (Alan Bawden), +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00038.html">"is that useful?"</a> (Walter C. Pelissero), and +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00040.html">"l, the ultimate curry that is not curry"</a> (Al Petrofsky).<p> +- +-<H3>Why are the macro called <code>cut/cute</code> and not +-[<em>enter your favourite here</em>]?</H3> ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00018.html">"OK, how about...,"</a> (Alan Bawden), ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00038.html">"is that useful?"</a> (Walter C. Pelissero), and ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00040.html">"l, the ultimate curry that is not curry"</a> (Al Petrofsky). ++</p> + ++<h3>Why are the macro called <code>cut/cute</code> and not ++[<em>enter your favourite here</em>]?</h3> ++<p> + Well, the original name proposed for this SRFI was <code>curry</code> + which immediately stirred some emotions as it does not what is + commonly known as currying. +@@ -306,23 +352,26 @@ concept is often called in other programming languages, + but I tend to remember it as the acronym for "Curry Upon This" ;-). + The names for the evaluating version of <code>cut</code> that + have been proposed were <code>cut!</code>, <code>cutlet</code>, +-<code>cut*</code>, and <code>cute</code>.<p> +- +-<H3>Is it possible to implement the SRFI without macros?</H3> ++<code>cut*</code>, and <code>cute</code>. ++</p> + ++<h3>Is it possible to implement the SRFI without macros?</h3> ++<p> + Not really. + As Stephan Houben has pointed out during the discussion (refer to +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00008.html">"Implementing it as a procedure"</a>) it is possible to implement the ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00008.html">"Implementing it as a procedure"</a>) it is possible to implement the + <code>cute</code>-mechanism as a procedure. + Refer also to Al Petrofsky's posting +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00048.html">"Problems with "curry"'s formal specification"</a> for details. ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00048.html">"Problems with "curry"'s formal specification"</a> for details. + However, the procedural implementation comes with a slight performance + penalty and it is not possible the implement the <code>cut</code>-mechanism + as a procedure, too. + As both are needed, we rely on macros to implement the SRFI. ++</p> + +-<H3>Why is there another symbol for the rest-slot when lambda-expressions +-use the dotted notation for variable length argument lists?</H3> ++<h3>Why is there another symbol for the rest-slot when lambda-expressions ++use the dotted notation for variable length argument lists?</h3> ++<p> + There are two reasons. + The first one is the existence of a procedural implementation + of a related mechanism (refer to the previous paragraph). +@@ -330,10 +379,11 @@ For a procedure, however, it is not possible to have dotted notation. + The second reason is the way the hygienic macro mechanism in R5RS + is defined to deal with dotted notation, as Felix Winkelmann has pointed out. + Refer to the discussion threads +-<a href="http://srfi.schemers.org/srfi-26/mail-archive/msg00001.html">"Improper lists in macros [WAS: none]"</a>.<p> ++<a href="https://srfi.schemers.org/srfi-26/mail-archive/msg00001.html">"Improper lists in macros [WAS: none]"</a>. ++</p> + +-<H3>Why is it impossible to specify when a non-slot is evaluated individually +-per non-slot?</H3> ++<h3>Why is it impossible to specify when a non-slot is evaluated individually per non-slot?</h3> ++<p> + <code>Cut</code> evaluates all non-slots at the time the specialized + procedure is called and <code>cute</code> evaluates all non-slots at + the time the procedure is being specialized. +@@ -343,32 +393,34 @@ However, I am convinced that the benefit of the greater flexibility + is not worth the risk of confusion. + If a piece of code really depends on the distinction, it might be + better to make this explicit through <code>let</code> and +-<code>lambda</code>.<p> +- +-<H3>Why is <code>(cut if <> 0 1)</code> etc. illegal?</H3> ++<code>lambda</code>. ++</p> + ++<h3>Why is <code>(cut if <> 0 1)</code> etc. illegal?</h3> ++<p> + It is specified that a <code><slot-or-expr></code> must be + either the slot symbol or an <code><expression></code> in the sense +-of <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.1.3"><I>R5RS, +-Section 7.1.3</I></a>. ++of <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%25_sec_7.1.3"><i>R5RS, ++Section 7.1.3</i></a>. + As <code>if</code> is no <code><expression></code>, + the above case is illegal. + The reason why <code>cut</code> and <code>cute</code> are + restricted in this sense is the difficulty of defining + the meaning of such generalized expressions. + Please refer to the discussion archive for details. ++</p> + +-<H1>Acknowledgements</H1> +- ++<h2>Acknowledgements</h2> ++<p> + An important part of this SRFI is based on the contribution + of other people, mostly through the discussion archive. + In particular, the semantics and the design rationale have + been greatly improved in the course of the discussion. + I would like to thank all who have contributed. ++</p> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Sebastian Egner (2002). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -392,12 +444,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <address>Author: <a href="mailto:sebastian.egner@philips.com">Sebastian Egner</a></address> + <!-- Created: Mon Feb 4 15:20:00 EST 2002 --> + <!-- hhmts start --> +-Last modified: Wed Jun 19 10:54:36 MST 2002 ++Last modified: Sun Jan 28 13:40:30 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html +index 14a88ff..c568d78 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-27.html +@@ -1,55 +1,67 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-27 ┃ ++┃ Commit: d8ae06a9786f66693830fa1064627b563d42e61c ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 27: Sources of Random Bits</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> +- + <body> +- +-<H1>Title</H1> +- +-SRFI 27: Sources of Random Bits +- +-<H1>Author</H1> +- +-Sebastian Egner +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access +-previous messages via +-<a href="http://srfi.schemers.org/srfi-27/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +-<UL> +-<LI>Draft: 2002/02/12-2002/04/12</LI> +-<LI>Revised: 2002/04/04 +-<LI>Revised: 2002/04/10 +-<LI>Revised: 2002/04/10 +-<LI>Final: 2002/06/03 +-</UL> +- +-<H1>Abstract</H1> +- ++<h1>SRFI 27: Sources of Random Bits</h1> ++ ++<p>by Sebastian Egner</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 27 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-27/srfi-27.html">https://srfi.schemers.org/srfi-27/srfi-27.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+27+at+srfi+dotschemers+dot+org">srfi-27@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-27">archive</a>.</p> ++<ul> ++<li>Draft: 2002-02-12--2002-04-12</li> ++<li>Revised: 2002-04-04 ++</li><li>Revised: 2002-04-10 ++</li><li>Revised: 2002-04-10 ++</li><li>Final: 2002-06-03 ++</li></ul> ++ ++<h2>Abstract</h2> ++<p> + This document specifies an interface to sources of random bits, + or "random sources" for brevity. + In particular, there are three different ways to use the interface, + with varying demands on the quality of the source and the +-amout of control over the production process: +- +-<UL> +-<LI> ++amount of control over the production process: ++</p> ++<ul> ++<li> + The "no fuss" interface specifies that +-<code>(random-integer </code><I>n</I><code>)</code> +-produces the next random integer in {0, ..., <I>n</I>-1} and ++<code>(random-integer </code><i>n</i><code>)</code> ++produces the next random integer in {0, ..., <i>n</i>-1} and + <code>(random-real)</code> produces the next random + real number between zero and one. + The details of how these random values are produced may not be + very relevant, as long as they appear to be sufficiently random. +-<LI> ++</li> ++<li> + For simulation purposes, on the contrary, it is usually necessary + to know that the numbers are produced deterministically by a pseudo + random number generator of high quality and to have explicit access +@@ -57,18 +69,19 @@ to its state. + In addition, one might want to use several independent sources of + random numbers at the same time and it can be useful to have some + simple form of randomization. +-<LI> ++</li> ++<li> + For security applications a serious form of true randomization + is essential, in the sense that it is difficult for an adversary to + exploit or introduce imperfections into the distribution of random bits. + Moreover, the linear complexity of the stream of random bits is more + important than its statistical properties. +-In these applications, an entropy source (producing truly random ++In these applications, an entropy source (producing truely random + bits at a low rate) is used to randomize a pseudo random number + generator to increase the rate of available bits. +-</UL> ++</li> ++</ul> + <p> +- + Once random sources provide the infrastructure to obtain + random bits, these can be used to construct other random deviates. + Most important are floating point numbers of various distributions +@@ -78,17 +91,20 @@ limited use elsewhere), we do not include them in this SRFI. + In other words, this SRFI is <em>not</em> about making + all sorts of random objects---it is about obtaining random + bits in a portable, flexible, reliable, and efficient way. ++</p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + ++<p> + This SRFI defines an interface for sources of random bits + computed by a pseudo random number generator. + The interface provides range-limited integer and real numbers. + It allows accessing the state of the underlying generator. + Moreover, it is possible to obtain a large number of + independent generators and to invoke a mild form of true +-randomization.<p> +- ++randomization. ++</p> ++<p> + The design aims at sufficient flexibility to cover the + usage patterns of many applications as diverse as + discrete structures, numerical simulations, and cryptographic protocols. +@@ -96,8 +112,9 @@ At the same time, the interface aims at simplicity, + which is important for occasional use. + As there is no "one size fits all" random number generator, + the design necessarily represents some form of compromise +-between the needs of the various applications.<p> +- ++between the needs of the various applications. ++</p> ++<p> + Although strictly speaking not part of the specification, + the emphasis of this proposal is on <em>high quality</em> + random numbers and on <em>high performance</em>. +@@ -105,51 +122,49 @@ As the state of the art in pseudo random number generators + is still advancing considerably, the choice of method for + the reference implementation should essentially be + considered preliminary. ++</p> + +-<H1>Specification</H1> +- +-<DL> +- +-<DT><a name="random-integer"></a> +-<code>(random-integer </code><I>n</I><code>) -> </code><I>x</I><code></code> +-</DT> ++<h2>Specification</h2> + +-<DD> +-The next integer <I>x</I> in {0, ..., <I>n</I>-1} ++<dl> ++<dt id="random-integer"> ++<code>(random-integer </code><i>n</i><code>) -> </code><i>x</i><code></code> ++</dt> ++<dd> ++<p> ++The next integer <i>x</i> in {0, ..., <i>n</i>-1} + obtained from <code>default-random-source</code>. + Subsequent results of this procedure appear to be independent +-uniformly distributed over the range {0, ..., <I>n</I>-1}. +-The argument <I>n</I> must be a positive integer, ++uniformly distributed over the range {0, ..., <i>n</i>-1}. ++The argument <i>n</i> must be a positive integer, + otherwise an error is signalled. +-</DD> +- +-</DL> +- +-<DL> +- +-<DT><a name="random-real"></a> +-<code>(random-real) -> </code><I>x</I><code></code> +-</DT> +- +-<DD> +-The next number 0 < <I>x</I> < 1 obtained from ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="random-real"> ++<code>(random-real) -> </code><i>x</i><code></code> ++</dt> ++<dd> ++<p> ++The next number 0 < <i>x</i> < 1 obtained from + <code>default-random-source</code>. + Subsequent results of this procedure appear to be + independent uniformly distributed. + The numerical type of the results and the + quantization of the output range depend on the implementation; + refer to <code>random-source-make-reals</code> for details. +-</DD> +- +-</DL> +- +-<DL> ++</p> ++</dd> ++</dl> + +-<DT><a name="default-random-source"></a> ++<dl> ++<dt id="default-random-source"> + <code>default-random-source</code> +-</DT> +- +-<DD> ++</dt> ++<dd> ++<p> + A random source from which <code>random-integer</code> and + <code>random-real</code> have been derived using + <code>random-source-make-integers</code> and +@@ -157,18 +172,18 @@ A random source from which <code>random-integer</code> and + Note that an assignment to <code>default-random-source</code> + does not change <code>random</code> or <code>random-real</code>; + it is also strongly recommended not to assign a new value. +-</DD> +- +-</DL> +-<HR ALIGN=left WIDTH="10%"> +-<DL> +- +-<DT><a name="make-random-source"></a> +-<code>(make-random-source) -> </code><I>s</I><code></code> +-</DT> +- +-<DD> +-Creates a new random source <I>s</I>. ++</p> ++</dd> ++</dl> ++ ++<hr align="left" width="10%" /> ++<dl> ++<dt id="make-random-source"> ++<code>(make-random-source) -> </code><i>s</i><code></code> ++</dt> ++<dd> ++<p> ++Creates a new random source <i>s</i>. + Implementations may accept additional, optional arguments in + order to create different types of random sources. + A random source created with <code>make-random-source</code> +@@ -177,146 +192,148 @@ by some form of pseudo random number generator. + Each random source obtained as <code>(make-random-source)</code> + generates the same stream of values, unless the state is modified + with one of the procedures below. +-</DD> +- +-</DL> +- +-<DL> +- +-<DT><a name="random-source-p"></a> +-<code>(random-source? </code><I>obj</I><code>) -> </code><I>bool</I><code></code> +-</DT> +- +-<DD> +-Tests if <I>obj</I> is a random source. ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="random-source-p"> ++<code>(random-source? </code><i>obj</i><code>) -> </code><i>bool</i><code></code> ++</dt> ++<dd> ++<p> ++Tests if <i>obj</i> is a random source. + Objects of type random source are distinct from all + other types of objects. +-</DD> +- +-</DL> +- +-<DL> +- +-<DT><a name="random-source-state-ref"></a> +-<code>(random-source-state-ref </code><I>s</I><code>) -> </code><I>state</I><code></code><br> +-<code>(random-source-state-set! </code><I>s</I><code> </code><I>state</I><code>)</code> +-</DT> +- +-<DD> +-Get and set the current state of a random source <I>s</I>. The +-structure of the object <I>state</I> depends on the implementation; ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="random-source-state-ref"> ++<code>(random-source-state-ref </code><i>s</i><code>) -> </code><i>state</i><code></code><br /> ++<code>(random-source-state-set! </code><i>s</i><code> </code><i>state</i><code>)</code> ++</dt> ++<dd> ++<p> ++Get and set the current state of a random source <i>s</i>. The ++structure of the object <i>state</i> depends on the implementation; + the only portable use of it is as argument to + <code>random-source-state-set!</code>. + It is, however, required that a state possess an external + representation. +-</DD> +- +-</DL> +- +-<DL> +-<DT><a name="random-source-randomize!"></a> +-<code>(random-source-randomize! </code><I>s</I><code>)</code> +-</DT> +- +-<DD> ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="random-source-randomize!"> ++<code>(random-source-randomize! </code><i>s</i><code>)</code> ++</dt> ++<dd> ++<p> + Makes an effort to set the state of the random +-source <I>s</I> to a truly random state. ++source <i>s</i> to a truly random state. + The actual quality of this randomization depends on the implementation +-but it can at least be assumed that the procedure sets <I>s</I> to a ++but it can at least be assumed that the procedure sets <i>s</i> to a + different state for each subsequent run of the Scheme system. +-</DD> +-</DL> +- +-<DL> +-<DT><a name="random-source-pseudo-randomize!"></a> +-<code>(random-source-pseudo-randomize! </code><I>s</I><code> <I>i</I> <I>j</I>)</code> +-</DT> +- +-<DD> +-Changes the state of the random source <I>s</I> into the initial +-state of the (<I>i</I>, <I>j</I>)-th independent random source, +-where <I>i</I> and <I>j</I> are non-negative integers. ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="random-source-pseudo-randomize!"> ++<code>(random-source-pseudo-randomize! </code><i>s</i><code> <i>i</i> <i>j</i>)</code> ++</dt> ++<dd> ++<p> ++Changes the state of the random source <i>s</i> into the initial ++state of the (<i>i</i>, <i>j</i>)-th independent random source, ++where <i>i</i> and <i>j</i> are non-negative integers. + This procedure provides a mechanism to obtain a large number of + independent random sources (usually all derived from the same backbone + generator), indexed by two integers. + In contrast to <code>random-source-randomize!</code>, + this procedure is entirely deterministic. +-</DD> +-</DL> +- +- +-<HR ALIGN=left WIDTH="10%"> ++</p> ++</dd> ++</dl> + +-<DL> + +-<DT><a name="random-source-make-integers"></a> +-<code>(random-source-make-integers </code><I>s</I><code>) -> </code><I>rand</I><code></code> +-</DT> ++<hr align="left" width="10%" /> + +-<DD> +-Obtains a procedure <I>rand</I> to generate random integers +-using the random source <I>s</I>. +-<I>Rand</I> takes a single argument <I>n</I>, ++<dl> ++<dt id="random-source-make-integers"> ++<code>(random-source-make-integers </code><i>s</i><code>) -> </code><i>rand</i><code></code> ++</dt> ++<dd> ++<p> ++Obtains a procedure <i>rand</i> to generate random integers ++using the random source <i>s</i>. ++<i>Rand</i> takes a single argument <i>n</i>, + which must be a positive integer, and returns the next uniformly +-distributed random integer from the interval {0, ..., <I>n</I>-1} +-by advancing the state of the source <I>s</I>.<p> +- ++distributed random integer from the interval {0, ..., <i>n</i>-1} ++by advancing the state of the source <i>s</i>. ++</p> ++<p> + If an application obtains and uses several generators for the same +-random source <I>s</I>, a call to any of these generators advances +-the state of <I>s</I>. Hence, the generators <em>do not</em> produce ++random source <i>s</i>, a call to any of these generators advances ++the state of <i>s</i>. Hence, the generators <em>do not</em> produce + the same sequence of random integers each but rather share a state. + This also holds for all other types of generators derived from + a fixed random sources. + Implementations that support concurrency make sure that +-the state of a generator is properly advanced.<p> +-</DD> +- +-</DL> +- +-<DL> +- +-<DT><a name="random-source-make-reals"></a> +-<code>(random-source-make-reals </code><I>s</I><code>) -> </code><I>rand</I><code></code><br> +-<code>(random-source-make-reals </code><I>s</I><code> </code><I>unit</I><code>) -> </code><I>rand</I><code></code><br> +-</DT> +- +-<DD> +-Obtains a procedure <I>rand</I> to generate random real numbers +-0 < <I>x</I> < 1 using the random source <I>s</I>. +-The procedure <I>rand</I> is called without arguments.<p> +- +-The optional parameter <I>unit</I> determines the type of numbers +-being produced by <I>rand</I> and the quantization of the output. +-<I>Unit</I> must be a number such that 0 < <I>unit</I> < 1. +-The numbers created by <I>rand</I> are of the same numerical +-type as <I>unit</I> and the potential output values are +-spaced by at most <I>unit</I>. One can imagine <I>rand</I> +-to create numbers as <I>x</I>*<I>unit</I> where <I>x</I> +-is a random integer in {1, ..., floor(1/<I>unit</I>)-1}. ++the state of a generator is properly advanced.</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt id="random-source-make-reals"> ++<code>(random-source-make-reals </code><i>s</i><code>) -> </code><i>rand</i><code></code><br /> ++<code>(random-source-make-reals </code><i>s</i><code> </code><i>unit</i><code>) -> </code><i>rand</i><code></code><br /> ++</dt> ++<dd> ++<p> ++Obtains a procedure <i>rand</i> to generate random real numbers ++0 < <i>x</i> < 1 using the random source <i>s</i>. ++The procedure <i>rand</i> is called without arguments. ++</p> ++<p> ++The optional parameter <i>unit</i> determines the type of numbers ++being produced by <i>rand</i> and the quantization of the output. ++<i>Unit</i> must be a number such that 0 < <i>unit</i> < 1. ++The numbers created by <i>rand</i> are of the same numerical ++type as <i>unit</i> and the potential output values are ++spaced by at most <i>unit</i>. One can imagine <i>rand</i> ++to create numbers as <i>x</i>*<i>unit</i> where <i>x</i> ++is a random integer in {1, ..., floor(1/<i>unit</i>)-1}. + Note, however, that this need not be the way the values + are actually created and that the actual resolution of +-<I>rand</I> can be much higher than <I>unit</I>. +-In case <I>unit</I> is absent it defaults to a reasonably ++<i>rand</i> can be much higher than <i>unit</i>. ++In case <i>unit</i> is absent it defaults to a reasonably + small value (related to the width of the mantissa of an + efficient number format). +-</DD> +- +-</DL> ++</p> ++</dd> ++</dl> + + +-<H1>Design Rationale</H1> ++<h2>Design Rationale</h2> + +-<H3>Why not combine <code>random-integer</code> and +-<code>random-real</code>?</H3> ++<h3>Why not combine <code>random-integer</code> and <code>random-real</code>?</h3> + ++<p> + The two procedures are not combined into a single variable-arity + procedures to save a little time and space during execution. + Although some Scheme systems can deal with variable arity as + efficiently as with fixed arity this is not always the case + and time efficiency is very important here. ++</p> + +-<H3>Why not some object-oriented interface?</H3> ++<h3>Why not some object-oriented interface?</h3> + ++<p> + There are many alternatives to the interface as specified in this SRFI. + In particular, every framework for object-orientation can be used to + define a class for random sources and specify the interface for the +@@ -324,9 +341,11 @@ methods on random sources. + However, as the object-oriented frameworks differ considerably + in terms of syntax and functionality, this SRFI does not make + use of any particular framework. ++</p> + +-<H3>Why is there not just a generator with a fixed range?</H3> ++<h3>Why is there not just a generator with a fixed range?</h3> + ++<p> + A bare fixed-range generator is of very limited use. + Nearly every application has to add some functionality + to make use of the random numbers. +@@ -337,22 +356,26 @@ This is exactly what is provided by + In addition, is saves the user from the pitfall of changing + the range with a simple <code>modulo</code>-computation + which may substantially reduce the quality of the +-numbers being produced.<p> +- ++numbers being produced. ++</p> ++<p> + The design of the interface is based on three prototype applications: +-<OL> +-<LI> ++</p> ++<ol> ++<li> + Repeatedly choose from relatively small sets: + As the size of the set is likely to vary from call to call, +-<code>random-integer</code> accepts a range argument <I>n</I> in every call. ++<code>random-integer</code> accepts a range argument <i>n</i> in every call. + The implementation should try to avoid boxing/unboxing of values + if the ranges fit into immediate integers. +-<LI> ++</li> ++<li> + Generate a few large integers with a fixed number of bits: + As generating the random number itself is expensive, + passing the range argument in every call does not hurt performance. + Hence, the same interface as in the first application can be used. +-<LI> ++</li> ++<li> + Generate real numbers: + Unlike the choose-from-set case, + the range and the quantization is constant over a +@@ -365,10 +388,11 @@ Therefore, + <code>random-real</code> does not accept any parameters but + the procedure <code>random-source-make-reals</code> creates + a properly configured <code>random-real</code> procedure. +-</OL> +- +-<H3>Why bother about floating point numbers at all?</H3> ++</li> ++</ol> + ++<h3>Why bother about floating point numbers at all?</h3> ++<p> + A proper floating point implementation of a random number generator + is potentially much more efficient that an integer implementation + because it can use more powerful arithmetics hardware. +@@ -378,19 +402,21 @@ produce floating point random numbers. + A secondary reason is to save the user from the 'not as easy as + it seems' task of converting an integer generator into a real + generator. ++</p> + +-<H3>Why are zero and one excluded from <code>random-real</code>?</H3> +- ++<h3>Why are zero and one excluded from <code>random-real</code>?</h3> ++<p> + The procedure <code>random-real</code> does not return +-<I>x</I> = 0 or <I>x</I> = 1 in order to allow +-<code>(log </code><I>x</I><code>)</code> and +-<code>(log (- 1 </code><I>x</I>)<code>)</code> ++<i>x</i> = 0 or <i>x</i> = 1 in order to allow ++<code>(log </code><i>x</i><code>)</code> and ++<code>(log (- 1 </code><i>x</i>)<code>)</code> + without the danger of a numerical exception. ++</p> + +-<H1>Implementation</H1> +- +-<H3>Choice of generator</H3> ++<h2>Implementation</h2> + ++<h3>Choice of generator</h3> ++<p> + The most important decision about the implementation is + the choice of the random number generator. + The basic principle here is: <em>Let quality prevail!</em> +@@ -399,8 +425,9 @@ a cheap price to pay for some avoided catastrophes. + It may be unexpected, but I have also seen many examples + where the better generator was also the faster. + Simple linear congruential generator cannot be recommended +-as they tend to be ill-behaved in several ways.<p> +- ++as they tend to be ill-behaved in several ways. ++</p> ++<p> + For this reason, my initial proposal was George Marsaglia's + COMBO generator, which is the combination of a 32-bit + multiplicative lagged Fibonacci-generator with a 16-bit +@@ -408,16 +435,17 @@ multiply with carry generator. + The COMBO generator passes all tests of Marsaglia's + <a href="http://stat.fsu.edu/~geo/diehard.html">DIEHARD</a> + testsuite for random number generators and has +-a period of order 2^60.<p> +- ++a period of order 2^60. ++</p> ++<p> + As an improvement, Brad Lucier suggested +-<a href="http://srfi.schemers.org/srfi-27/mail-archive/msg00000.html">suggested</a> ++<a href="https://srfi.schemers.org/srfi-27/mail-archive/msg00000.html">suggested</a> + Pierre L'Ecuyer's + <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/combmrg2.ps">MRG32k3a</a> + generator which is combination of two recursive generators + of degree three, both of which fit into 54-bit arithmetics. + The MRG32k3a generator also passes DIEHARD and in addition, +-has desirable spectral properties and a period in the ++has desireable spectral properties and a period in the + order of 2^191. + As a matter of fact, multiple recursive generators (MRGs) are + theoretically much better understood than special constructions +@@ -425,10 +453,12 @@ as the COMBO generator. + This is the reason why the implementations provided here + implements the MRG32k3a generator. + When implemented in floating point arithmetics with sufficient +-mantissa-width, this generator is also very fast.<p> ++mantissa-width, this generator is also very fast. ++</p> + +-<H3>Choice of arithmetics</H3> ++<h3>Choice of arithmetics</h3> + ++<p> + The next important decision about the implementation is + the type of arithmetics to be used. + The choice is difficult and depends heavily on the +@@ -441,8 +471,9 @@ And if you do not have floats either, then at least + try to make sure you work with immediate integers + (instead of allocated objects). + Unfortunately, there is no portable way in Scheme to +-find out about native and emulated arithmetics.<p> +- ++find out about native and emulated arithmetics. ++</p> ++<p> + As performance is critical to many applications, + one might want to implement the actual + generator itself in native code. +@@ -450,17 +481,20 @@ For this reason, I provide three different + implementations of the backbone generator + as a source of inspiration. + See the code below. ++</p> + +-<H3>Data Type for Random Sources</H3> ++<h3>Data Type for Random Sources</h3> + ++<p> + An important aspect of the specification in this SRFI + is that random sources are objects of a distinct type. + Although this is straight-forward and available in nearly + every Scheme implementation, there is no portable way + to do this at present. + One way to define the record type is to use +-<a href="http://srfi.schemers.org/srfi-9/">SRFI-9</a>.<p> +- ++<a href="srfi-9.html">SRFI-9</a>. ++</p> ++<p> + The reference implementations below define a record + type to contain the exported procedures. + The actual state of the generator is stored in the +@@ -468,42 +502,51 @@ binding time environment of <code>make-random-source</code>. + This has the advantage that access to the state is fast + even if the record type would be slow (which need not be + the case). ++</p> + +-<H3>Entropy Source for Randomization</H3> ++<h3>Entropy Source for Randomization</h3> + ++<p> + Another problematic part of the specification with respect + to portability is <code>random-source-randomize!</code> as +-it needs access to a real entropy source.<p> +- ++it needs access to a real entropy source. ++</p> ++<p> + A reasonable choice for such as source is to use the system + clock in order to obtain a value for randomization, for example + in the way John David Stone recommends (see reference below). + This is good enough for most applications with the + notable exception of security related programs. + One way to obtain the time in Scheme is to use +-<a href="http://srfi.schemers.org/srfi-19/">SRFI-19</a>.<p> ++<a href="srfi-19.html">SRFI-19</a>. ++</p> + +-<H3>Implementation of the specified interface</H3> ++<h3>Implementation of the specified interface</h3> + ++<p> + Once the portability issues are resolved, + one can provide the remaining functionality as +-specified in this SRFI document.<p> +- ++specified in this SRFI document. ++</p> ++<p> + For the reference implementation, a relatively large part + of the code deals with the more advanced features of the + MRG32k3a generator, + in particular <code>random-source-pseudo-randomize!</code>. + This code is inspired by Pierre L'Ecuyer's own implementation +-of the MRG32k3a generator.<p> +- ++of the MRG32k3a generator. ++</p> ++<p> + Another part of this generic code deals with changing + the range and quantization of the random numbers and +-with error checking to detect common mistakes and abuses.<p> ++with error checking to detect common mistakes and abuses. ++</p> + +-<H3>Implementation Examples</H3> ++<h3>Implementation Examples</h3> + +-<a href="http://srfi.schemers.org/srfi-27/reference">Here</a> are three alternative implementations of the SRFI. +-(<a href="http://srfi.schemers.org/srfi-27/srfi-27-reference.tar.gz">Here</a> are all files, tar-gzipped, 13300 bytes.) ++<p> ++<a href="https://srfi.schemers.org/srfi-27/reference">Here</a> are three alternative implementations of the SRFI. ++(<a href="https://srfi.schemers.org/srfi-27/srfi-27.tgz">Here</a> are all files, tar-gzipped, 53K bytes.) + Keep in mind that a SRFI is a "request for implementation", + which means these implementations are merely examples + to illustrate the specification and inspire people to implement +@@ -513,35 +556,35 @@ on a Pentium3, 800 Mhz, Linux; <i>x</i> int/s, <i>y</i> real/s + means <code>(random-integer 2)</code> can be computed about <i>x</i> + times a second and <code>(random-real)</code> about <i>y</i> times a second. + The implementations are ++</p> + +-<OL type="a"> +- +-<LI> for Scheme 48 0.57, using 54-bit <code>integer</code> only. ++<ol type="a"> ++<li> for Scheme 48 0.57, using 54-bit <code>integer</code> only. + This implementation aims at portability, not at performance + (30000 ints/s, 3000/s reals/s). +- +-<LI> for Scheme 48 0.57 with the core generator being implemented ++</li> ++<li> for Scheme 48 0.57 with the core generator being implemented + in C using <code>(double)</code>-arithmetics. + The generator is made available in Scheme 48 via the + <a href="http://s48.org/0.57/manual/s48manual_52.html">C/Scheme + interface</a>. + The performance of this generator is good + (160000 ints/s, 180000 reals/s). +- +-<LI> for Gambit 3.0, using <code>flonum</code> and ++</li> ++<li> for Gambit 3.0, using <code>flonum</code> and + 54-bit <code>integer</code>. + This code is inspired by a program by Brad Lucier as +-<a href="http://srfi.schemers.org/srfi-27/mail-archive/msg00000.html">posted</a> ++<a href="https://srfi.schemers.org/srfi-27/mail-archive/msg00000.html">posted</a> + to the discussion archive of this SRFI. + The performance of this generator is good when compiled + (5000 ints/s, 25000/s reals/s when interpreted, + 200000 ints/s, 400000/s reals/s when compiled; + see acknowledgements). +- +-</OL> +- ++</li> ++</ol> ++<p> + In addition to the implementations there is a small +-collection of <a href="http://srfi.schemers.org/srfi-27/conftest.scm">confidence tests</a> ++collection of <a href="https://srfi.schemers.org/srfi-27/reference/conftest.scm">confidence tests</a> + for the interface specified. + The tests merely check a few assertions expressed by the specification. + It is not the intention to provide a complete test of the interface here. +@@ -550,12 +593,13 @@ generator itself. + However, there is a function to write random bits from + the generators to a file in a way readable by the <em>DIEHARD</em> + testsuite. This makes it easier for implementors to find out +-about their favorite generators and check their implementation.<p> +- ++about their favorite generators and check their implementation. ++</p> + + +-<H1>Recommended Usage Patterns</H1> ++<h2>Recommended Usage Patterns</h2> + ++<p> + Unless the functionality defined in this SRFI is sufficient, + an application has to implement more procedures to construct + other random deviates. +@@ -565,24 +609,27 @@ examples of increasing difficulty + with respect to the interface. + Note that the code below is not part of the specification, + it is merely meant to illustrate the spirit ++</p> + +-<H3>Generating Random Permutations</H3> ++<h3>Generating Random Permutations</h3> + ++<p> + The following code defines procedures to generate random +-permutations of the set {0, ..., <I>n</I>-1}. ++permutations of the set {0, ..., <i>n</i>-1}. + Such a permutation is represented by a <code>vector</code> +-of length <I>n</I> for the images of the points.<p> +- ++of length <i>n</i> for the images of the points. ++</p> ++<p> + Observe that the implementation first defines the procedure + <code>random-source-make-permutations</code> to +-turn a random source <I>s</I> into a procedure to generate +-permutations of given degree <I>n</I>. ++turn a random source <i>s</i> into a procedure to generate ++permutations of given degree <i>n</i>. + In a second step, this is applied to the default source + to define a ready-to-use procedure for permutations: +-<code>(random-permutation </code><I>n</I><code>)</code> +-constructs a random permutation of degree <I>n</I>. +- +-<code><pre> ++<code>(random-permutation </code><i>n</i><code>)</code> ++constructs a random permutation of degree <i>n</i>. ++</p> ++<pre> + (define (random-source-make-permutations s) + (let ((rand (random-source-make-integers s))) + (lambda (n) +@@ -601,19 +648,21 @@ constructs a random permutation of degree <I>n</I>. + + (define random-permutation + (random-source-make-permutations default-random-source)) +-</pre></code> +- ++</pre> ++<p> + For the algorithm refer to Knuth's "The Art of Computer Programming", + Vol. II, 2nd ed., Algorithm P of Section 3.4.2. ++</p> + +-<H3>Generating Exponentially-Distributed Random Numbers</H3> ++<h3>Generating Exponentially-Distributed Random Numbers</h3> + ++<p> + The following code defines procedures to generate exponentially + Exp(mu)-distributed random numbers. + The technical difficulty of the interface addressed here is + how to pass optional arguments to <code>random-source-make-reals</code>. +- +-<code><pre> ++</p> ++<pre> + (define (random-source-make-exponentials s . unit) + (let ((rand (apply random-source-make-reals s unit))) + (lambda (mu) +@@ -621,17 +670,20 @@ how to pass optional arguments to <code>random-source-make-reals</code>. + + (define random-exponential + (random-source-make-exponentials default-random-source)) +-</pre></code> +- ++</pre> ++<p> + The algorithm is folklore. Refer to Knuth's "The Art of Computer + Programming", Vol. II, 2nd ed., Section 3.4.1.D. ++</p> + +-<H3>Generating Normally-Distributed Random Numbers</H3> ++<h3>Generating Normally-Distributed Random Numbers</h3> + ++<p> + The following code defines procedures to generate + normal N(mu, sigma)-distributed real numbers using +-the polar method.<p> +- ++the polar method. ++</p> ++<p> + The technical difficulty of the interface addressed here + is that the polar method generates two results per computation. + We return one of the result and store the second one to be +@@ -639,8 +691,8 @@ returned by the next call to the procedure. + Note that this implies that <code>random-source-state-set!</code> + (and the other procedures modifying the state) does not necessarily + affect the output of <code>random-normal</code> immediately! +- +-<code><pre> ++</p> ++<pre> + (define (random-source-make-normals s . unit) + (let ((rand (apply random-source-make-reals s unit)) + (next #f)) +@@ -653,7 +705,7 @@ affect the output of <code>random-normal</code> immediately! + (let* ((v1 (- (* 2 (rand)) 1)) + (v2 (- (* 2 (rand)) 1)) + (s (+ (* v1 v1) (* v2 v2)))) +- (if (>= s 1) ++ (if (>= s 1) + (loop) + (let ((scale (sqrt (/ (* -2 (log s)) s)))) + (set! next (* scale v2)) +@@ -661,38 +713,40 @@ affect the output of <code>random-normal</code> immediately! + + (define random-normal + (random-source-make-normals default-random-source)) +-</pre></code> +- ++</pre> ++<p> + For the algorithm refer to Knuth's "The Art of Computer Programming", + Vol. II, 2nd ed., Algorithm P of Section 3.4.1.C. ++</p> + +-<H1>Acknowledgements</H1> +- ++<h2>Acknowledgements</h2> ++<p> + I would like to thank all people who have participated in the discussion, + in particular Brad Lucier and Pierre l'Ecuyer. + Their contributions have greatly improved the design of this SRFI. + Moreover, Brad has optimized the Gambit implementation quite substantially. ++</p> + +-<H1>References</H1> ++<h2>References</h2> + +-<OL> ++<ol> + +-<LI> ++<li> + G. Marsaglia: + Diehard -- Testsuite for Random Number Generators. + <a href="http://stat.fsu.edu/~geo/diehard.html">stat.fsu.edu/~geo/diehard.html</a> + (Also contains some generators that do pass Diehard.) +-</LI> ++</li> + +-<LI> ++<li> + D. E. Knuth: + The Art of Computer Programming; + Volume II Seminumerical Algorithms. + 2nd ed. Addison-Wesley, 1981. + (The famous chapter on random number generators.) +-</LI> ++</li> + +-<LI> ++<li> + P. L'Ecuyer: + "Software for Uniform Random Number Generation: + Distinguishing the Good and the Bad", +@@ -700,93 +754,92 @@ Moreover, Brad has optimized the Gambit implementation quite substantially. + IEEE Press, Dec. 2001, 95--105. + <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wsc01rng.pdf">www.iro.umontreal.ca/~lecuyer/myftp/papers/wsc01rng.pdf</a> + (Profound discussion of random number generators.) +-</LI> ++</li> + +-<LI> ++<li> + P. L'Ecuyer: + "Good Parameter Sets for Combined Multiple Recursive + Random Number Generators", + Shorter version in Operations Research, 47, 1 (1999), 159--164. + <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/combmrg2.ps">www.iro.umontreal.ca/~lecuyer/myftp/papers/combmrg2.ps</a> + (Actual numbers for good generators.) +-</LI> ++</li> + +-<LI> ++<li> + P. L'Ecuyer: + "Software for Uniform Random Number Generation: + Distinguishing the Good and the Bad", + Proceedings of the 2001 Winter Simulation Conference, + IEEE Press, Dec. 2001, 95--105. +-</LI> ++</li> + +-<LI> ++<li> + MIT Scheme v7.6: + <code>random flo:random-unit *random-state* make-random-state + random-state?</code> + <a href="http://www.swiss.ai.mit.edu/projects/scheme/documentation/scheme_5.html#SEC53">http://www.swiss.ai.mit.edu/projects/scheme/documentation/scheme_5.html#SEC53</a> + (A mechanism to run a fixed unspecified generator.) +-</LI> ++</li> + +-<LI> ++<li> + A. Jaffer: + SLIB 2d2 with (require 'random): +- <code>random *random-state* copy-random-state seed->random-state ++ <code>random *random-state* copy-random-state seed->random-state + make-random-state random:uniform random:exp random:normal-vector! + random-hollow-sphere! random:solid-sphere!</code> +- <a href="http://www.swiss.ai.mit.edu/~jaffer/slib_4.html#SEC92">http://www.swiss.ai.mit.edu/~jaffer/slib_4.html#SEC92</a> +- (Based on the MIT Scheme mechanism.) +-</LI> ++ <a href="http://swiss.csail.mit.edu/~jaffer/slib_5.html#SEC108">http://swiss.csail.mit.edu/~jaffer/slib_5.html#SEC108</a> ++ (Uses RC-4.) ++</li> + +-<LI> ++<li> + R. Kelsey, J. Rees: + Scheme 48 v0.57 'random.scm': + <code>make-random make-random-vector</code> + (Internal procedures of Scheme48; a fixed 28-bit generator.) +-</LI> ++</li> + +-<LI> ++<li> + M. Flatt: + PLT MzScheme Version 200alpha1: + <code>random random-seed current-pseudo-random-generator + make-pseudo-random-generator pseudo-random-generator?</code> +- <a href="http://download.plt-scheme.org/doc/200alpha1/html/mzscheme/mzscheme-Z-H-3.html#%_idx_144">http://download.plt-scheme.org/doc/200alpha1/html/mzscheme/mzscheme-Z-H-3.html#%_idx_144</a> ++ <a href="http://download.plt-scheme.org/doc/200alpha1/html/mzscheme/mzscheme-Z-H-3.html#%25_idx_144">http://download.plt-scheme.org/doc/200alpha1/html/mzscheme/mzscheme-Z-H-3.html#%_idx_144</a> + (A mechanism to run a generator and to exchange the generator.) +-</LI> ++</li> + +-<LI> ++<li> + H. Abelson, G. J. Sussmann, J. Sussman: + Structure and Interpretation of Computer Programs. +- <a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_idx_2934">http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_idx_2934</a> ++ <a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%25_idx_2934">http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_idx_2934</a> + (The <code>rand</code>-example shows a textbook way to define a + random number generator.) +-</LI> ++</li> + +-<LI> ++<li> + John David Stone: + A portable random-number generator. + <a href="http://www.math.grin.edu/~stone/events/scheme-workshop/random.html">http://www.math.grin.edu/~stone/events/scheme-workshop/random.html</a> + (An implementation of a linear congruental generator in Scheme.) +-</LI> ++</li> + +-<LI> ++<li> + Network Working Group: + RFC1750: Randomness Recommendations for Security. + <a href="http://www.cis.ohio-state.edu/htbin/rfc/rfc1750.html">http://www.cis.ohio-state.edu/htbin/rfc/rfc1750.html</a> + (A serious discussion of serious randomness for serious security.) +-</LI> ++</li> + +-<LI> +- <a href="http://www.random.org/essay.html">http://www.random.org/essay.html</a><br> ++<li> ++ <a href="http://www.random.org/essay.html">http://www.random.org/essay.html</a><br /> + <a href="http://www.taygeta.com/random/randrefs.html">http://www.taygeta.com/random/randrefs.html</a> + (Resources on random number generators and randomness.) +-</LI> ++</li> + +-</OL> ++</ol> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Sebastian Egner (2002). All Rights Reserved.</p> +- + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -810,12 +863,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <address>Author: <a href="mailto:sebastian.egner@philips.com">Sebastian Egner</a></address> + <!-- Created: Mon Feb 4 18:17 EST 2002 --> + <!-- hhmts start --> +-Last modified: Fri Sep 5 16:11:17 MST 2003 ++Last modified: Wed Jul 21 08:44:49 MST 2010 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html +index 8aae23b..c2a0de5 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-28.html +@@ -1,41 +1,58 @@ +-<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> +- <meta name="generator" content="HTML Tidy, see www.w3.org"> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-28 ┃ ++┃ Commit: bc52eea48b47b656a9733f4a5af53ca0e4ec89ba ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <meta content="HTML Tidy, see www.w3.org" name="generator" /> + <title>SRFI 28: Basic Format Strings</title> +- <meta name="author" content="Scott G. Miller"> +- <meta name="description" content="Basic Format Strings"> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ <meta content="Scott G. Miller" name="author" /> ++ <meta content="Basic Format Strings" name="description" /> + </head> + + <body> + +- <H1>Title</H1> ++ <h1>SRFI 28: Basic Format Strings</h1> + +- SRFI 28: Basic Format Strings ++ <p>by Scott G. Miller</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 28 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-28/srfi-28.html">https://srfi.schemers.org/srfi-28/srfi-28.html</a>.</p></blockquote></blockquote></blockquote> + +- <H1>Author</H1> ++ <h2>Status</h2> + +- Scott G. Miller ++ <p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+28+at+srfi+dotschemers+dot+org">srfi-28@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-28">archive</a>.</p> ++<ul> ++ <li>Draft: 2002-03-23--2002-05-23</li> ++ <li>Final: 2002-06-25 ++ </li></ul> + +- <H1>Status</H1> +- +- This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +- +- You can access the discussion on this SRFI via <a href="http://srfi.schemers.org/srfi-28/mail-archive/maillist.html">the archive of the mailing list</a>. +- +- <ul> +- <li>Draft: 2002/03/23-2002/05/23</li> +- <li>Final: 2002/06/25 +- </ul> +- +- <H1>Abstract</H1> ++ <h2>Abstract</h2> + + This document specifies Format Strings, a method of + interpreting a Scheme string which contains a number of escape + sequences that are replaced with other string data according to + the semantics of each sequence. + +- <H1>Rationale</H1> ++ <h2>Rationale</h2> + + Many Scheme systems provide access to a function called <tt> + format.</tt> This function takes as arguments a format string, +@@ -47,9 +64,9 @@ + allow portable code to be written using the function without + much (if any) effort on the part of Scheme implementors. + +- <H1>Specification</H1> ++ <h2>Specification</h2> + +- <b><a name="format"></a><tt>format</tt></b> <tt><i>format-string [obj ...] -> ++ <b><tt id="format">format</tt></b> <tt><i>format-string [obj ...] -> + string</i></tt> + + <blockquote> +@@ -84,7 +101,7 @@ + value.</p> + </blockquote> + +- <h2>Examples</h2> ++ <h3>Examples</h3> + <pre> + (format "Hello, ~a" "World!") + ; => "Hello, World!" +@@ -93,10 +110,10 @@ + ; => "Error, list is too short: (one \"two\" 3))" + </pre> + +- <H1>Implementation</H1> ++ <h2>Implementation</h2> + + The implementation below requires SRFI-6 (Basic string ports) +- and SRFI-23 (Error reporting mechanism). <br> ++ and SRFI-23 (Error reporting mechanism). <br /> + + <pre> + (define format +@@ -134,7 +151,7 @@ + + </pre> + +- <H1>Copyright</H1> ++ <h2>Copyright</h2> + + <p>Copyright (C) Scott G. Miller (2002). All Rights Reserved.</p> + +@@ -161,10 +178,10 @@ + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </p> +- <hr> ++ <hr /> + + <address> +- Editor: <a href="mailto:srfi-editors@srfi.schemers.org"> ++ Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org"> + Francisco Solsona</a> + </address> + +@@ -178,4 +195,3 @@ + <!-- hhmts end --> + </body> + </html> +- +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html +index e493c05..bc144b0 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-29.html +@@ -1,36 +1,46 @@ +-<!DOCTYPE html> ++<!DOCTYPE html SYSTEM "about:legacy-compat"> + <html lang="en"> + <head> +- <meta name="generator" content= +- "HTML Tidy for HTML5 for Linux version 5.8.0"> +- <meta charset="utf-8"> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-29 ┃ ++┃ Commit: 8f06116fce5c7cadedf90ce754239d15198e5ab6 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 29: Localization</title> +- <link href="/favicon.png" rel="icon" sizes="192x192" type= +- "image/png"> +- <link rel="stylesheet" href="https://srfi.schemers.org/srfi.css" +- type="text/css"> +- <meta name="viewport" content= +- "width=device-width, initial-scale=1"> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> + </head> + <body> +- <h1><a href="https://srfi.schemers.org/"><img class="srfi-logo" +- src="https://srfi.schemers.org/srfi-logo.svg" alt= +- "SRFI surfboard logo"></a>29: Localization</h1> ++ <h1>SRFI 29: Localization</h1> + + <p>by Scott G. Miller</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 29 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-29/srfi-29.html">https://srfi.schemers.org/srfi-29/srfi-29.html</a>.</p></blockquote></blockquote></blockquote> + + <h2 id="status">Status</h2> + + <p>This SRFI is currently in <em>final</em> status. Here is + <a href="https://srfi.schemers.org/srfi-process.html">an + explanation</a> of each status that a SRFI can hold. To provide +- input on this SRFI, please send email to <code><a href= +- "mailto:srfi+minus+29+at+srfi+dotschemers+dot+org">srfi-29@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. +- To subscribe to the list, follow <a href= +- "https://srfi.schemers.org/srfi-list-subscribe.html">these ++ input on this SRFI, please send email to <code><a href="mailto:srfi+minus+29+at+srfi+dotschemers+dot+org">srfi-29@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. ++ To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these + instructions</a>. You can access previous messages via the +- mailing list <a href= +- "https://srfi-email.schemers.org/srfi-29">archive</a>.</p> ++ mailing list <a href="https://srfi-email.schemers.org/srfi-29">archive</a>.</p> + + <ul> + <li>Draft: 2002-03-26--2002-06-19</li> +@@ -124,9 +134,9 @@ + no-argument procedures:</p> + + <p><b><code id="current-language">current-language</code></b> +- <code>-> <i>symbol</i></code><br> ++ <code>-> <i>symbol</i></code><br /> + <code><b>current-language</b> <i>symbol</i> -> +- undefined</code><br></p> ++ undefined</code><br /></p> + + <blockquote> + When given no arguments, returns the current ISO 639-1 language +@@ -137,9 +147,9 @@ + </blockquote> + + <p><b><code id="current-country">current-country</code></b> +- <code>-> <i>symbol</i></code><br> ++ <code>-> <i>symbol</i></code><br /> + <code><b>current-country</b> <i>symbol</i> -> +- undefined</code><br></p> ++ undefined</code><br /></p> + + <blockquote> + returns the current ISO 3166-1 country code as a symbol. +@@ -149,11 +159,10 @@ + is not possible). + </blockquote> + +- <p><b><code id= +- "current-locale-details">current-locale-details</code></b> +- <code>-> <i>list of symbol</i></code>s<br> ++ <p><b><code id="current-locale-details">current-locale-details</code></b> ++ <code>-> <i>list of symbol</i></code>s<br /> + <code><b>current-locale-details</b> <i>list-of-symbols</i> -> +- undefined</code><br></p> ++ undefined</code><br /></p> + + <blockquote> + Returns a list of additional locale details as a list of +@@ -211,7 +220,7 @@ + + <p><b><code id="declare-bundle!">declare-bundle!</code></b> + <code><i>bundle-specifier association-list</i> -> +- undefined<br></code></p> ++ undefined<br /></code></p> + + <blockquote> + Declares a new bundle named by the given bundle-specifier. +@@ -219,10 +228,10 @@ + association list. The list contains associations between + Scheme symbols and the message templates (Scheme strings) they + name. If a bundle already exists with the given name, it +- is overwritten with the newly declared bundle.<br> ++ is overwritten with the newly declared bundle.<br /> + </blockquote> + <code id="store-bundle"><b>store-bundle</b> +- <i>bundle-specifier</i> -> boolean</code><br> ++ <i>bundle-specifier</i> -> boolean</code><br /> + + <blockquote> + Attempts to store a bundle named by the given bundle specifier, +@@ -231,10 +240,10 @@ + an unspecified mechanism that may be persistent across Scheme + system restarts. If successful, a non-false value is + returned. If unsuccessful, <code>#f</code> is +- returned.<br> ++ returned.<br /> + </blockquote> + <code id="load-bundle!"><b>load-bundle!</b> +- <i>bundle-specifier</i> -> boolean</code><br> ++ <i>bundle-specifier</i> -> boolean</code><br /> + + <blockquote> + Attempts to retrieve a bundle from an unspecified mechanism +@@ -243,7 +252,7 @@ + non-false value, and the bundle is immediately available to the + Scheme system. If the bundle could not be found or loaded + successfully, the function returns <code>#f</code>, and the +- Scheme system's bundle registry remains unaffected.<br> ++ Scheme system's bundle registry remains unaffected.<br /> + </blockquote> + + <p>A compliant Scheme system may choose not to provide any +@@ -259,14 +268,14 @@ + + <p><b><code id="localized-template">localized-template</code></b> + <i><code>package-name message-template-name</code></i> +- <code>-> <i>string or #f<br></i></code></p> ++ <code>-> <i>string or #f<br /></i></code></p> + + <blockquote> + Retrieves a localized message template for the given package + name and the given message template name (both symbols). + If no such message could be found, false (#f) is +- returned.<br> +- <br> ++ returned.<br /> ++ <br /> + </blockquote> + + <p>After retrieving a template, the calling program can use +@@ -324,7 +333,7 @@ + of those functions in the reference implementation are not + capable of that distinction. Their implementation is provided + only so that the following code can run in any R4RS scheme +- system. <br></p> ++ system. <br /></p> + + <p>In addition, the below implementation of a compliant + <code>format</code> requires SRFI-6 (Basic String Ports) and +@@ -500,11 +509,10 @@ + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE.</p> + +- <hr> ++ <hr /> + + <address> +- Editor: <a href= +- "mailto:srfi+minus+editors+at+srfi+dot+schemers+dot+org">David ++ Editor: <a href="mailto:srfi+minus+editors+at+srfi+dot+schemers+dot+org">David + Rush</a> + </address> + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html +index b6c2fdc..ee5fafa 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-30.html +@@ -1,63 +1,69 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-30 ┃ ++┃ Commit: d7239fe0de9f0c68e99feb90b2512c3ae343a202 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 30: Nested Multi-line Comments</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 30: Nested Multi-line Comments</h1> + +-SRFI 30: Nested Multi-line Comments ++<p>by Martin Gasbichler</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 30 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-30/srfi-30.html">https://srfi.schemers.org/srfi-30/srfi-30.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> + +-<H1>Author</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+30+at+srfi+dotschemers+dot+org">srfi-30@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-30">archive</a>.</p> + +-Martin Gasbichler +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. It will +-remain in draft until 2002-04-06, or as amended. to provide input on +-this SRFI, please +-<a href="mailto:srfi-30@srfi.schemers.org"> +-mail to <code>srfi-30@srfi.schemers.org</code></a>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html"> +-instructions here</a> to subscribe to the list. You can access +-previous messages via +-<a href="http://srfi.schemers.org/srfi-30/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-30/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +-<UL> +- <LI>Draft: 2002/04/12-2002/06/10</LI> +- <li>Revised: 2002/06/05</li> +- <li>Final: 2002/08/07</li> +-</UL> +- +- <h1>Related SRFIs</h1> ++<ul> ++ <li>Draft: 2002-04-12--2002-06-10</li> ++ <li>Revised: 2002-06-05</li> ++ <li>Final: 2002-08-07</li> ++</ul> ++ ++ <h2>Related SRFIs</h2> + +- <p><a href="http://srfi.schemers.org/srfi-22/">SRFI 22</a> defines ++ <p><a href="https://srfi.schemers.org/srfi-22/">SRFI 22</a> defines + a multi line comment that may only appear at the beginning of a + file.</p> + +- <p><a href="http://srfi.schemers.org/srfi-10/">SRFI 10</a> +- proposes the notation ++ <p><a href="https://srfi.schemers.org/srfi-10/">SRFI 10</a> ++ proposes the notation</p> + +- <PRE> "#" <discriminator> <other-char>*</PRE> for further +- SRFIs that introduce values which may be read and written.</p> ++ <pre> "#" <discriminator> <other-char>*</pre> ++ <p>for further SRFIs that introduce values which may be read and ++ written.</p> + +- <H1>Abstract</H1> ++ <h2>Abstract</h2> + + <p>This SRFI extends R5RS by possibly nested, multi-line + comments. Multi-line comments start with <code>#|</code> and end + with <code>|#</code>.</p> + +- <H1>Rationale</H1> ++ <h2>Rationale</h2> + + <p>Multi-line comments are common to many programming languages. They + provide a convenient mean for adding blocks of text inside a program and +@@ -70,13 +76,11 @@ the archive of the mailing list</a>. + with R5RS. Nested comments are an important feature for + incrementally commenting out code.</p> + +- <H1>Specification</H1> ++ <h2 id="spec">Specification</h2> + +- <p>This SRFI extends the specification of comments -- <a +- href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-5.html#%_sec_2.2">R5RS ++ <p>This SRFI extends the specification of comments -- <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-5.html#%25_sec_2.2">R5RS + section 2.2</a> -- as follows:</p> + +- <a name="spec"></a> + <p>The sequence <code>#|</code> indicates the start of a + multi-line comment. The multi-line comment continues until + <code>|#</code> appears. If the closing <code>|#</code> is +@@ -88,8 +92,7 @@ the archive of the mailing list</a>. + + <p>This SRFI furthermore extends the production for + <code><comment></code> in the specification of lexical +- structure -- <a +- href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.1.1">R5RS ++ structure -- <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%25_sec_7.1.1">R5RS + section 7.1.1</a> -- to: + </p> + <pre> +@@ -101,11 +104,10 @@ the archive of the mailing list</a>. + </pre> + + +- <h1><code><delimiter></code> and <code>#</code></h1> ++ <h2><code><delimiter></code> and <code>#</code></h2> + + <p>The SRFI does not extend the specification of +- <code><delimiter></code> from <a +- href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.1.1">R5RS ++ <code><delimiter></code> from <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%25_sec_7.1.1">R5RS + section 7.1.1</a>. It is therefore required to separate tokens + which require implicit termination (identifiers, numbers, + characters, and dot) from multi-line comments by a +@@ -116,7 +118,7 @@ the archive of the mailing list</a>. + incompatible with existing implementations which allow + <code>#</code> as legal character within identifiers.</p> + +- <H1>Implementation</H1> ++ <h2>Implementation</h2> + + <p>The following procedure <code>skip-comment</code> deletes a + leading multi-line comment from the current input port. Its +@@ -143,7 +145,7 @@ the archive of the mailing list</a>. + ((#\#) (lp 'read-sharp nested-level)) + (else (lp 'start nested-level)))) + ((read-bar) (case (next-char) +- ((#\#) (if (> nested-level 1) ++ ((#\#) (if (> nested-level 1) + (lp 'start (- nested-level 1)))) + (else (lp 'start nested-level)))) + ((read-sharp) (case (next-char) +@@ -151,18 +153,16 @@ the archive of the mailing list</a>. + (else (lp 'start nested-level))))))) + </pre> + +- <p>A <a href="http://srfi.schemers.org/srfi-22/">SRFI 22</a> script to remove nested multi-line comments is ++ <p>A <a href="https://srfi.schemers.org/srfi-22/">SRFI 22</a> script to remove nested multi-line comments is + available at + +- <a +- href="http://srfi.schemers.org/srfi-30/remove-srfi30-comments-script.scm">http://srfi.schemers.org/srfi-30/remove-srfi30-comments-script.scm</a>. ++ <a href="https://srfi.schemers.org/srfi-30/remove-srfi30-comments-script.scm">https://srfi.schemers.org/srfi-30/remove-srfi30-comments-script.scm</a>. + + The script will read a Scheme program containing nested + multi-line comments from standard input and emit the same + programs with the comments removed to standard output. The + script mimics the Scheme 48 reader and uses the +- <code>error</code> procedure from <a +- href="http://srfi.schemers.org/srfi-23/">SRFI 23</a>.</p> ++ <code>error</code> procedure from <a href="srfi-23.html">SRFI 23</a>.</p> + + <p>A number of Scheme implemenations already support this SRFI: + Chez Scheme, Chicken, Gambit-C, Kawa, MIT Scheme, MzScheme and +@@ -171,7 +171,7 @@ the archive of the mailing list</a>. + implementations, Scheme 48 and Guile do not support this SRFI + yet.</p> + +- <H1>Copyright</H1> ++ <h2>Copyright</h2> + <p>Copyright (C) Martin Gasbichler (2002). All Rights Reserved.</p> + + <p> +@@ -199,12 +199,11 @@ the archive of the mailing list</a>. + </p> + + +- <hr> +- <address>Editor: <a +- href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Sun Sep 1 17:14:55 MST 2002 ++Last modified: Sun Jan 28 13:40:31 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html +index faf6eb9..dd8dc91 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-31.html +@@ -1,306 +1,319 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> +- <meta http-equiv=Content-Type content="text/html; charset=windows-1252"> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-31 ┃ ++┃ Commit: 14d0782ac5c30079f79495e75bd5eb0d7b4edb49 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 31: A special form `rec' for recursive evaluation</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 31: A special form <code>rec</code> for recursive evaluation</h1> + +-SRFI 31: A special form <CODE>rec</CODE> for recursive evaluation ++<p>by Mirko Luedde</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 31 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-31/srfi-31.html">https://srfi.schemers.org/srfi-31/srfi-31.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Mirko Luedde <<a href="mailto:Mirko.Luedde@SAP.com">Mirko.Luedde@SAP.com</a>> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+31+at+srfi+dotschemers+dot+org">srfi-31@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-31">archive</a>.</p> ++<ul> ++ <li>Draft: 2002-05-24--2002-08-24</li> ++ <li>Revised: 2002-08-12</li> ++ <li>Final: 2002-12-02</li> ++</ul> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <A +-HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +- +-You can access the discussion via <A +-HREF="http://srfi.schemers.org/srfi-31/mail-archive/maillist.html">the +-archive of the mailing list</A>. +- +-<UL> +- <LI>Draft: 2002/05/24-2002/08/24</LI> +- <LI>Revised: 2002/08/12</LI> +- <LI>Final: 2002/12/02</LI> +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + We propose the implementation of a special form +-called <CODE>rec</CODE>. This form is a generalization and +-combination of the forms <CODE>rec</CODE> and +-<CODE>named-lambda</CODE> of <A +-href="#[Clinger1985]">[Clinger1985]</A>. It allows the simple and ++called <code>rec</code>. This form is a generalization and ++combination of the forms <code>rec</code> and ++<code>named-lambda</code> of <a href="#%5BClinger1985%5D">[Clinger1985]</a>. It allows the simple and + non-imperative construction of self-referential expressions. As an + important special case, it extends the A. Church form +-<CODE>lambda</CODE> such that it allows the direct definition of ++<code>lambda</code> such that it allows the direct definition of + recursive procedures without using further special forms like +-<CODE>let</CODE> or <CODE>letrec</CODE>, without using advanced ++<code>let</code> or <code>letrec</code>, without using advanced + constructions like the H. B. Curry combinator and, unlike +-<CODE>define</CODE>, without introducing variable bindings into the ++<code>define</code>, without introducing variable bindings into the + external environment. + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + +-<H2>General</H2> Among the prominent features of the Scheme +-programming language as defined in <a href="#[KCR1998]">[KCR1998]</a> ++<h3>General</h3> Among the prominent features of the Scheme ++programming language as defined in <a href="#%5BKCR1998%5D">[KCR1998]</a> + are the following. + +-<OL> ++<ol> + +- <LI>It has simple syntax.</LI> ++ <li>It has simple syntax.</li> + +- <LI>It encourages recursive definitions, e.g. by ensuring memory +- efficient tail recursion.</LI> ++ <li>It encourages recursive definitions, e.g. by ensuring memory ++ efficient tail recursion.</li> + +- <LI>It supports non-imperative programming.</LI> ++ <li>It supports non-imperative programming.</li> + +-</OL> ++</ol> + + Nevertheless Scheme does not provide a syntax for recursive + evaluations with the properties of + +-<OL> ++<ol> + +-<LI>being as simple, intuitive and close to the mathematical standard +-notation as possible,</LI> ++<li>being as simple, intuitive and close to the mathematical standard ++notation as possible,</li> + +-<LI>allowing general recursion,</LI> ++<li>allowing general recursion,</li> + +-<LI>being non-imperative.</LI> ++<li>being non-imperative.</li> + +-</OL> ++</ol> + +-<H2>Example</H2> +- +-<H3>Problem 1</H3> ++<h3>Example</h3> + ++<h4>Problem 1</h4> ++<p> + Let us look at the factorial function. In mathematical notation this + function is expressed as +- +-<PRE> +- (F : N |--> 1, if N = 0; ++</p> ++<pre> ++ (F : N |--> 1, if N = 0; + N * F(N - 1), otherwise). +-</PRE> +- ++</pre> ++<p> + This expression is a term and not a definition or proposition. +- +-<P>We investigate some approaches to express the factorial function in +-Scheme. +- +-<UL> +- +-<LI> ++</p> ++<p> ++We investigate some approaches to express the factorial function in Scheme. ++</p> ++<ul> ++<li> ++<p> + The simplest way perhaps is as +- +-<PRE> ++</p> ++<pre> + (define (F N) + (if (zero? N) 1 + (* N (F (- N 1))))) +-</PRE> +- ++</pre> ++<p> + But this expression is not a term. It binds the factorial function to + the variable <code>F</code>. The expression itself may not occur in a +-syntactical context where a name of the factorial is required.</LI> +- +-<LI> ++syntactical context where a name of the factorial is required. ++</p> ++</li> ++<li> ++<p> + We list several ways to express the factorial as a function term. +- +-<OL> +- +-<LI> +-<PRE> ++</p> ++<ol> ++<li> ++<pre> + (let () + (define (F N) + (if (zero? N) 1 + (* N (F (- N 1))))) + F) +-</PRE> +-</LI> +- +-<LI> +-<PRE> ++</pre> ++</li> ++<li> ++<pre> + (lambda (N) + (let F ( (N N) ) + (if (zero? N) 1 + (* N (F (- N 1)))))) +-</PRE> +-</LI> ++</pre> ++</li> + +-<LI> +-<PRE> ++<li> ++<pre> + (letrec ( (F (lambda (N) + (if (zero? N) 1 + (* N (F (- N 1)))))) ) F) +-</PRE> +-</LI> ++</pre> ++</li> + +-<LI> +-<PRE> ++<li> ++<pre> + ((lambda (F) + (F F)) + (lambda (G) + (lambda (N) + (if (zero? N) 1 + (* N ((G G) (- N 1))))))) +-</PRE> +-</LI> +- +-</OL> ++</pre> ++</li> + ++</ol> ++<p> + All these expressions define the factorial anonymously, not binding it + to a variable. However, all these expressions are more verbose than it + seems necessary and they are less intuitive than it seems +-desirable. </LI> +- +-</UL> ++desirable. ++</p> ++</li> + +-<H3>Solution 1</H3> ++</ul> + +-A solution to our problem was already provided in <A +-href="#[Clinger1985]">[Clinger1985]</A> by the form +-<CODE>named-lambda</CODE>. An even earlier solution with a slightly ++<h4>Solution 1</h4> ++<p> ++A solution to our problem was already provided in <a href="#%5BClinger1985%5D">[Clinger1985]</a> by the form ++<code>named-lambda</code>. An even earlier solution with a slightly + different syntax was implemented in Kent Dybvig's Chez Scheme system. +- ++</p><p> + Using this special form, we can denote the factorial simply by +- +-<PRE> ++</p> ++<pre> + (named-lambda (F N) + (if (zero? N) 1 + (* N (F (- N 1))))) +-</PRE> +- ++</pre> ++<p> + This expression is a function term that denotes the factorial in the + appropriate brevity. + +-<P>However, the form <code>named-lambda</code> has been dropped from ++</p><p>However, the form <code>named-lambda</code> has been dropped from + later versions of the Scheme Report. Also it is missing in + state-of-the-art implementations such as Chez Scheme (6.0a) and MIT + Scheme (7.7.0). (The latter actually knows a form +-<CODE>named-lambda</CODE> with different semantics). ++<code>named-lambda</code> with different semantics). ++</p> + +-<H3>Problem 2</H3> ++<h4>Problem 2</h4> + + The constant stream of ones can be defined via + +-<PRE>(define S (cons 1 (delay S)))</PRE> ++<pre>(define S (cons 1 (delay S)))</pre> + + As in the case of the factorial, we are able to define the recursive + object at the price of spending an externally bound name. Remedying +-this with <CODE>let</CODE> or <CODE>letrec</CODE> leads to similar ++this with <code>let</code> or <code>letrec</code> leads to similar + objections as above. + +-<H3>Solution 2</H3> +- ++<h4>Solution 2</h4> ++<p> + This particular case of the self-referential problem was solved by the +-<CODE>rec</CODE> form in <A href="#[Clinger1985]">[Clinger1985]</A>. +- ++<code>rec</code> form in <a href="#%5BClinger1985%5D">[Clinger1985]</a>. ++</p><p> + This form allows writing +- +-<PRE>(rec S (cons 1 (delay S)))</PRE> +- ++</p> ++<pre>(rec S (cons 1 (delay S)))</pre> ++<p> + This expression is non-imperative and does not introduce an external + variable binding. + +-<P>Also this form has been dropped from later versions of the Scheme ++</p><p>Also this form has been dropped from later versions of the Scheme + Report. Moreover, from our point of view this form alone is not + capable of solving Problem 1. The respective definition would look + like +- +-<PRE> ++</p> ++<pre> + (rec F + (lambda (N) + (if (zero? N) 1 + (* N (F (- N 1)))))) +-</PRE> +- ++</pre> ++<p> + This again does not seem quite as simple and intuitive as the + mathematical notation. ++</p> + +-<H2>Proposal</H2> ++<h3>Proposal</h3> + +-We therefore propose to implement the <CODE>rec</CODE> special form in ++We therefore propose to implement the <code>rec</code> special form in + a generalized way that combines the advantages of the +-<CODE>named-lambda</CODE> and <CODE>rec</CODE> forms. ++<code>named-lambda</code> and <code>rec</code> forms. + + The factorial function could be written +-<PRE> ++<pre> + (rec (F N) + (if (zero? N) 1 + (* N (F (- N 1))))) +-</PRE> ++</pre> + +-<H1>Specification</H1> ++<h2>Specification</h2> + +-<H2>Syntax</H2> ++<h3>Syntax</h3> + +-The following production rules are to be added to those of <a +-href="#[KCR1998]">[KCR1998]</a> (we reuse names of non-terminals). ++The following production rules are to be added to those of <a href="#%5BKCR1998%5D">[KCR1998]</a> (we reuse names of non-terminals). + +-<OL><a name="rec"></a> ++<ol id="rec"> + +-<LI><CODE><derived expression> --> <rec expression></CODE></LI> ++<li><code><derived expression> --> <rec expression></code></li> + +-<LI><CODE><rec expression> --> (rec <variable> +-<expression>)</CODE></LI> ++<li><code><rec expression> --> (rec <variable> ++<expression>)</code></li> + +-<LI><CODE><rec expression> --> (rec (<variable>+) +-<body>)</CODE></LI> ++<li><code><rec expression> --> (rec (<variable>+) ++<body>)</code></li> + +-</OL> ++</ol> + +-<H2>Semantics</H2> ++<h3>Semantics</h3> + +-Scheme versions such as <A href="#[KCR1998]">[KCR1998]</A> providing +-<CODE>define-syntax</CODE>, <CODE>syntax-rules</CODE>, +-<CODE>letrec</CODE> and <CODE>lambda</CODE> might implement +-<CODE>rec</CODE> as follows. ++Scheme versions such as <a href="#%5BKCR1998%5D">[KCR1998]</a> providing ++<code>define-syntax</code>, <code>syntax-rules</code>, ++<code>letrec</code> and <code>lambda</code> might implement ++<code>rec</code> as follows. + +-<PRE> ++<pre> + (define-syntax rec + (syntax-rules () + ((rec (NAME . VARIABLES) . BODY) + (letrec ( (NAME (lambda VARIABLES . BODY)) ) NAME)) + ((rec NAME EXPRESSION) + (letrec ( (NAME EXPRESSION) ) NAME)))) +-</PRE> ++</pre> + +-<H2>Test</H2> ++<h3>Test</h3> + +-The following session shows in which way <CODE>rec</CODE> allows a ++The following session shows in which way <code>rec</code> allows a + tail-recursive implementation of the factorial function. + +-<PRE> +-> (define F (rec (F N) ++<pre> ++> (define F (rec (F N) + ((rec (G K L) + (if (zero? K) L + (G (- K 1) (* K L)))) N 1))) +-> F ++> F + #<procedure> +-> (F 0) ++> (F 0) + 1 +-> (F 10) ++> (F 10) + 3628800 +-</PRE> ++</pre> + +-<H1>Acknowledgements</H1> ++<h2>Acknowledgements</h2> + + The author thanks Al Petrofsky for the final solution and Hal Abelson, + Chris Hanson and others for their input. The work of the maintainers + of the SRFI forum is highly appreciated. + +-<H1>Bibliography</H1> ++<h2>Bibliography</h2> + +-<UL> ++<ul> + +-<LI> ++<li> + <a name="[Clinger1985]">[Clinger1985]</a> + EDITOR = {Clinger, W.}, + TITLE = {Draft of Report of the October 1984 Workshop on Scheme}, +@@ -308,10 +321,9 @@ of the SRFI forum is highly appreciated. + MONTH = {Mar}, + YEAR = {1985}, + URL = +-{<A +-HREF=http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1985>http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1985</A>}</LI> ++{<a href="http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1985">http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1985</a>}</li> + +-<LI> ++<li> + <a name="[KCR1998]">[KCR1998]</a> + AUTHOR = {Kelsey, R. and Clinger, W. and Rees, J.}, + TITLE = {Revised (5) Report on the Algorithmic Language Scheme}, +@@ -320,10 +332,10 @@ HREF=http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1985>http://www.sw + NUMBER = {1}, + MONTH = {Sep}, + YEAR = {1998} +-</LI> +-</UL> ++</li> ++</ul> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + + <p>Copyright (C) Dr. Mirko Luedde (2002). All Rights Reserved.</p> + +@@ -350,11 +362,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +-<HR> ++<hr /> + +-<ADDRESS>Author: <A href="mailto:Mirko.Luedde@SAP.com">Mirko Luedde</A></ADDRESS> ++<address>Author: Mirko Luedde</address> + +-<ADDRESS>Editor: <A href="mailto:srfi-editors@srfi.schemers.org">Francisco Solsona</A></ADDRESS> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + + </body> + +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html +index aa46757..144337e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-34.html +@@ -1,82 +1,131 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> +-<title>SRFI 34: Exception Handling for Programs</title> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-34 ┃ ++┃ Commit: 33a6b84dea688dce5c867e795c4c553af2f8cdd9 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 34: Exception Handling for Programs</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> +-<H1>Title</H1> ++<h1>SRFI 34: Exception Handling for Programs</h1> + +-SRFI 34: Exception Handling for Programs ++<p>by Richard Kelsey and Michael Sperber</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 34 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-34/srfi-34.html">https://srfi.schemers.org/srfi-34/srfi-34.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Authors</H1> ++<h2>Status</h2> + +-Richard Kelsey and Michael Sperber ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+34+at+srfi+dotschemers+dot+org">srfi-34@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-34">archive</a>.</p> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. It will +-remain in draft until 2002-10-20, or as amended. to provide input on +-this SRFI, please mail to +-<a href="mailto:srfi-34@srfi.schemers.org"> +-<code>srfi-34@srfi.schemers.org</code></a>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html"> +-instructions here</a> to subscribe to the list. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-34/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-34/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +-<UL> +- <LI>Draft: 2002/07/24-2002/10/20</LI> +- <li>Revised: 2002/09/20</li> +- <li>Final: 2002/12/1</li> +- <LI>Fixed reference implementation: 2003/03/10</LI> +-</UL> ++<ul> ++ <li>Draft: 2002-07-24--2002-10-20</li> ++ <li>Revised: 2002-09-20</li> ++ <li>Final: 2002-12-01</li> ++ <li>Revised to fix errata: ++ <ul> ++ <li>2003-03-10</li> ++ <li>2018-01-13 (missing test in <code>guard-aux</code> implementation)</li> ++ </ul> ++ </li> ++</ul> + +-<h1>Abstract</h1> +-This SRFI defines exception-handling and exception-raising constructs for Scheme, including<ul><li>a <code>with-exception-handler</code> +- procedure and a <code>guard</code> +- form for installing exception-handling procedures,</li> +-<li>a <code>raise</code> +- procedure for invoking the current exception handler.</li> ++<h2>Abstract</h2> ++<p> ++ This SRFI defines exception-handling and exception-raising constructs for Scheme, including ++</p> ++<ul> ++ <li>a <code>with-exception-handler</code> ++ procedure and a <code>guard</code> ++ form for installing exception-handling procedures, ++ </li> ++ <li>a <code>raise</code> ++ procedure for invoking the current exception handler. ++ </li> + </ul> +-<p>This SRFI is based on (withdrawn) <a href="http://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> +-by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley.</p> +-<h1>Rationale</h1> +-<p>The goals of the exception mechanism specified in this SRFI are to help programmers share code which relies on exception handling, and to be easily added to existing Scheme systems.</p> +-<p>This SRFI is primarily useful in conjunction with one or more companion SRFIs:</p> +-<ul><li>a SRFI specifying exception-describing objects (conditions). An example is <a href="http://srfi.schemers.org/srfi-35">SRFI 35</a> +- (Conditions).</li> +-<li>a SRFI specifying a set of standard condition types to be raised by the primitives provided by the Scheme implementation, and requiring that certain Scheme primitives indeed raise exceptions within the framework described. An example is <a href="http://srfi.schemers.org/srfi-36">SRFI 36</a> +- (I/O Conditions).</li> +-<li>a SRFI specifying how computations may be resumed after an exception is raised.</li> ++<p> ++ This SRFI is based on (withdrawn) ++ <a href="https://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> ++ by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley. ++</p> ++<h2>Rationale</h2> ++<p> ++ The goals of the exception mechanism specified in this SRFI are to ++ help programmers share code which relies on exception handling, and ++ to be easily added to existing Scheme systems. ++</p> ++<p> ++ This SRFI is primarily useful in conjunction with one or more companion SRFIs: ++</p> ++<ul> ++ <li> ++ a SRFI specifying exception-describing objects (conditions). An ++ example is <a href="srfi-35.html">SRFI 35</a> ++ (Conditions). ++ </li> ++ <li> ++ a SRFI specifying a set of standard condition types to be raised ++ by the primitives provided by the Scheme implementation, and ++ requiring that certain Scheme primitives indeed raise exceptions ++ within the framework described. An example ++ is <a href="https://srfi.schemers.org/srfi-36/">SRFI 36</a> (I/O ++ Conditions). ++ </li> ++ <li> ++ a SRFI specifying how computations may be resumed after an exception is raised. ++ </li> + </ul> +-<h1>Specification</h1> ++<h2>Specification</h2> + <p>Exception handlers are one-argument procedures that determine the action the program takes when an exceptional situation is signalled. The system implicitly maintains a <i>current exception handler</i>.</p> + <p>The program raises an exception by invoking the current exception handler, passing to it an object encapsulating information about the exception. Any procedure accepting one argument may serve as an exception handler and any object may be used to represent an exception.</p> + <p>The system maintains the current exception handler as part of the <i>dynamic environment</i> of the program, akin to the current input or output port, or the context for <code>dynamic-wind</code>. The dynamic environment can be thought of as that part of a continuation that does not specify the destination of any returned values. It includes the current input and output ports, the <code>dynamic-wind</code> + context, and this SRFI's current exception handler. See the reference implementation for portable definitions of <code>current-dynamic-environment</code> + and <code>with-dynamic-environment</code>.</p> + <p>The initial current exception handler of the program is implementation-dependent. However, it should interrupt the program in some way visible to the user, either by aborting it, invoking a debugger, or some similar action.</p> +-<h2>Establishing Exception Handlers</h2> +-<dl><dt><a name="with-exception-handler"><code>(with-exception-handler </code><var>handler</var> +- <var>thunk</var><code>)</code></a></dt> +-<dd><p>Returns the result(s) of invoking <var>thunk</var>. <var>Handler</var> +- must be a procedure that accepts one argument. It is installed as the current exception handler for the dynamic extent (as determined by <code>dynamic-wind</code>) of the invocation of <var>thunk</var>.</p> ++<h3>Establishing Exception Handlers</h3> ++<dl> ++<dt id="with-exception-handler"><code>(with-exception-handler </code><var>handler</var> ++<var>thunk</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns the result(s) of ++ invoking <var>thunk</var>. <var>Handler</var> must be a procedure ++ that accepts one argument. It is installed as the current ++ exception handler for the dynamic extent (as determined ++ by <code>dynamic-wind</code>) of the invocation ++ of <var>thunk</var>. ++ </p> + </dd> + </dl> +-<dl><dt><a name="guard"><code>(guard </code><code>(</code> ++ ++<dl> ++<dt id="guard"><code>(guard </code><code>(</code> + <var> <clause<sub>1</sub> + > <clause<sub>2</sub> + > ...<code>)</code> +- <body><code>)</code></a> (syntax)</dt> +-<dd><p><em>Syntax:</em> ++<body><code>)</code> (syntax) ++</dt> ++<dd> ++<p><em>Syntax:</em> + Each <clause> should have the same form as a <code>cond</code> + clause</p> + <p><em>Semantics:</em> +@@ -91,17 +140,28 @@ by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley.</p> + expression.</p> + </dd> + </dl> +-<h2>Raising Exceptions</h2> +-<dl><dt><a name="raise"><code>(raise </code><var>obj</var><code>)</code></a></dt> +-<dd><p>Invokes the current exception handler on <var>obj</var>. The handler is called in the dynamic environment of the call to <code>raise</code>, except that the current exception handler is that in place for the call to <code>with-exception-handler</code> +- that installed the handler being called. The handler's continuation is otherwise unspecified.</p> ++ ++<h3>Raising Exceptions</h3> ++<dl> ++<dt id="raise"><code>(raise </code><var>obj</var><code>)</code> ++</dt> ++<dd> ++<p> ++ Invokes the current exception handler on <var>obj</var>. The handler ++ is called in the dynamic environment of the call ++ to <code>raise</code>, except that the current exception handler is ++ that in place for the call to <code>with-exception-handler</code> ++ that installed the handler being called. The handler's continuation ++ is otherwise unspecified. ++</p> + </dd> + </dl> +-<h1>Examples</h1> ++ ++<h2>Examples</h2> + <pre>(call-with-current-continuation + (lambda (k) + (with-exception-handler (lambda (x) +- (display "condition: ") ++ (display "condition: ") + (write x) + (newline) + (k 'exception)) +@@ -113,7 +173,7 @@ PRINTS: condition: an-error + (call-with-current-continuation + (lambda (k) + (with-exception-handler (lambda (x) +- (display "something went wrong") ++ (display "something went wrong") + (newline) + 'dont-care) + (lambda () +@@ -123,7 +183,7 @@ then behaves in an unspecified way + + (guard (condition + (else +- (display "condition: ") ++ (display "condition: ") + (write condition) + (newline) + 'exception)) +@@ -133,7 +193,7 @@ PRINTS: condition: an-error + + (guard (condition + (else +- (display "something went wrong") ++ (display "something went wrong") + (newline) + 'dont-care)) + (+ 1 (raise 'an-error))) +@@ -143,7 +203,7 @@ PRINTS: something went wrong + (call-with-current-continuation + (lambda (k) + (with-exception-handler (lambda (x) +- (display "reraised ") (write x) (newline) ++ (display "reraised ") (write x) (newline) + (k 'zero)) + (lambda () + (guard (condition +@@ -155,7 +215,7 @@ PRINTS: something went wrong + (call-with-current-continuation + (lambda (k) + (with-exception-handler (lambda (x) +- (display "reraised ") (write x) (newline) ++ (display "reraised ") (write x) (newline) + (k 'zero)) + (lambda () + (guard (condition +@@ -167,7 +227,7 @@ PRINTS: something went wrong + (call-with-current-continuation + (lambda (k) + (with-exception-handler (lambda (x) +- (display "reraised ") (write x) (newline) ++ (display "reraised ") (write x) (newline) + (k 'zero)) + (lambda () + (guard (condition +@@ -188,13 +248,14 @@ PRINTS: reraised 0 + ((assq 'b condition))) + (raise (list (cons 'b 23)))) + => (b . 23) +-</pre><h1>Reference Implementation</h1> +-<p>The reference implementation makes use of <a href="http://srfi.schemers.org/srfi-9/">SRFI 9</a> +- ("Defining Record Types"), and <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> +- ("Error reporting mechanism").</p> ++</pre> ++<h2>Reference Implementation</h2> ++<p>The reference implementation makes use of <a href="srfi-9.html">SRFI 9</a> ++ ("Defining Record Types"), and <a href="srfi-23.html">SRFI 23</a> ++ ("Error reporting mechanism").</p> + <pre>(define *current-exception-handlers* + (list (lambda (condition) +- (error "unhandled exception" condition)))) ++ (error "unhandled exception" condition)))) + + (define (with-exception-handler handler thunk) + (with-exception-handlers (cons handler *current-exception-handlers*) +@@ -214,7 +275,7 @@ PRINTS: reraised 0 + (with-exception-handlers (cdr handlers) + (lambda () + ((car handlers) obj) +- (error "handler returned" ++ (error "handler returned" + (car handlers) + obj))))) + +@@ -255,7 +316,7 @@ PRINTS: reraised 0 + (result temp) + (guard-aux reraise clause1 clause2 ...)))) + ((guard-aux reraise (test)) +- test) ++ (or test reraise)) + ((guard-aux reraise (test) clause1 clause2 ...) + (let ((temp test)) + (if temp +@@ -269,10 +330,11 @@ PRINTS: reraised 0 + (if test + (begin result1 result2 ...) + (guard-aux reraise clause1 clause2 ...))))) +-</pre><h1>References</h1> +-<ul><li><a href="http://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> ++</pre> ++<h2>References</h2> ++<ul><li><a href="https://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> + by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley</li> +-<li><a href="http://srfi.schemers.org/srfi-18/">SRFI 18: Multithreading support</a> ++<li><a href="https://srfi.schemers.org/srfi-18/">SRFI 18: Multithreading support</a> + by Marc Feeley</li> + <li>Richard Kelsey's <a href="http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1996/msg00022.html">1996 proposal</a> + </li> +@@ -280,8 +342,8 @@ by Marc Feeley</li> + by Dan Friedman, Chris Haynes, and Kent Dybvig</li> + <li>Kent Pitman's <a href="http://world.std.com/~pitman/Papers/Condition-Handling-2001.html">history paper</a> + </li> +-<li>The <a href="http://www.xanalys.com/software_tools/reference/HyperSpec/Body/09_.htm">Conditions chapter</a> +- from the <a href="http://www.xanalys.com/software_tools/reference/HyperSpec/Front/index.htm">Common Lisp HyperSpec</a> ++<li>The <a href="http://www.lispworks.com/documentation/HyperSpec/Body/09_.htm">Conditions chapter</a> ++ from the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/09_.htm">Common Lisp HyperSpec</a> + </li> + <li>The Conditions chapter by Kent M. Pitman in <a href="http://www-2.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/cltl2.html"><i>Common Lisp the Language, 2nd edition</i> + </a> +@@ -293,7 +355,7 @@ by Marc Feeley</li> + by Robert Harper</li> + </ul> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + + <p>Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights + Reserved.</p> +@@ -321,6 +383,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Francisco Solsona</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + </body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html +index de261a8..a369fca 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-35.html +@@ -1,71 +1,73 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html><head><title>SRFI 35: Conditions</title></head><body> +-<h1>Title</h1> +- +-Conditions +- +-<h1>Authors</h1> +- +-Richard Kelsey and Michael Sperber +- +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. It will +-remain in draft until 2002-10-20, or as amended. to provide input on +-this SRFI, please mail to +-<a href="mailto:srfi%20minus%2035%20at%20srfi%20dot%20schemers%20dot%20org"> +-<code>srfi minus 35 at srfi dot schemers dot org</code></a>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html"> +-instructions here</a> to subscribe to the list. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-35/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-34/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> ++<head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-35 ┃ ++┃ Commit: 658dc3ee853334f8c8af47606e4882db65e670dd ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 35: Conditions</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++</head> ++ ++<body> ++<h1>SRFI 35: Conditions</h1> ++ ++<p>by Richard Kelsey and Michael Sperber</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 35 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-35/srfi-35.html">https://srfi.schemers.org/srfi-35/srfi-35.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+35+at+srfi+dotschemers+dot+org">srfi-35@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-35">archive</a>.</p> + + <ul> +- <li>Draft: 2002/07/24-2002/10/20</li> +- <li>Revised: 2002/09/20</li> +- <li>Final: 2002/12/1</li> ++ <li>Draft: 2002-07-24--2002-10-20</li> ++ <li>Revised: 2002-09-20</li> ++ <li>Final: 2002-12-01</li> + </ul> + +-<h1>Abstract</h1> +-<p>The SRFI defines constructs for creating and inspecting <i>condition</i> +-types and values. A condition value encapsulates information about an +-exceptional situation, or exception. This SRFI also defines a few basic +-condition types.</p> +-<h1>Rationale</h1> +-<p>Conditions are values that communicate information about exceptional +-situations between parts of a program. Code that detects an exception +-may be in a different part of the program than the code that handles +-it. In fact, the former may have been written independently from the +-latter. Consequently, to facilitate effective handling of exceptions, +-conditions must communicate as much information as possible as +-accurately as possible, and still allow effective handling by code that +-did not precisely anticipate the nature of the exception that occurred.</p> +-<p>This SRFI provides two mechanisms to enable this kind of communication</p><ul><li>subtyping among condition types allows handling code to determine the <em>general</em> +- nature of an exception even though it does not anticipate its <em>exact</em> +- nature,</li> +-<li>compound conditions allow an exceptional situation to be described in multiple ways.</li> ++<h2>Abstract</h2> ++<p>The SRFI defines constructs for creating and inspecting <i>condition</i> types and values. A condition value encapsulates information about an exceptional situation, or exception. This SRFI also defines a few basic condition types.</p> ++<h2>Rationale</h2> ++<p>Conditions are values that communicate information about exceptional situations between parts of a program. Code that detects an exception may be in a different part of the program than the code that handles it. In fact, the former may have been written independently from the latter. Consequently, to facilitate effective handling of exceptions, conditions must communicate as much information as possible as accurately as possible, and still allow effective handling by code that did not precisely anticipate the nature of the exception that occurred.</p> ++<p>This SRFI provides two mechanisms to enable this kind of communication</p> ++<ul> ++ <li> ++ subtyping among condition types allows handling code to determine ++ the <em>general</em> nature of an exception even though it does ++ not anticipate its <em>exact</em> nature, ++ </li> ++ <li> ++ compound conditions allow an exceptional situation to be described ++ in multiple ways. ++ </li> + </ul> +-<p></p> +-<h1>Specification</h1> +-<p>Conditions are records with named fields. Each condition belongs to one or more <i>condition types</i>. +-Each condition type specifies a set of field names. A condition +-belonging to a condition type includes a value for each of the type's +-field names. These values can be extracted from the condition by using +-the appropriate field name.</p> ++ ++<h2>Specification</h2> ++<p>Conditions are records with named fields. Each condition belongs to one or more <i>condition types</i>. Each condition type specifies a set of field names. A condition belonging to a condition type includes a value for each of the type's field names. These values can be extracted from the condition by using the appropriate field name.</p> + <p>There is a tree of condition types with the distinguished <code>&condition</code> + as its root. All other condition types have a parent condition type.</p> +-<p>A condition belonging to several condition types with a common +-supertype may have distinct values for the supertype's fields for each +-type. The type used to access a field determines which of the values is +-returned. The program can extract each of these field values separately.</p> +-<h2>Procedures</h2> +-<dl><dt><code>(make-condition-type </code><var>id</var> ++<p>A condition belonging to several condition types with a common supertype may have distinct values for the supertype's fields for each type. The type used to access a field determines which of the values is returned. The program can extract each of these field values separately.</p> ++<h3>Procedures</h3> ++<dl> ++<dt><code>(make-condition-type </code><var>id</var> + <var>parent</var> + <var>field-names</var><code>)</code></dt> + <dd><p><code>Make-condition-type</code> +@@ -145,27 +147,28 @@ returns a condition of condition type <var>condition-type</var> + is a compound condition, <code>extract-condition</code> + extracts the field values from the subcondition belonging to <var>condition-type</var> + that appeared first in the call to <code>make-compound-condition</code> +- that created the condition. The returned condition may be newly created; it is possible for</p><pre>(let* ((&c (make-condition-type 'c &condition '())) ++ that created the the condition. The returned condition may be newly created; it is possible for ++</p> ++<pre>(let* ((&c (make-condition-type 'c &condition '())) + (c0 (make-condition &c)) + (c1 (make-compound-condition c0))) + (eq? c0 (extract-condition c1 &c))) +-</pre>to return false.<p></p> ++</pre> ++<p>to return false.</p> + </dd> + </dl> +-<h2>Macros</h2> +-<dl><dt><code>(define-condition-type </code><condition-type> <supertype> <predicate> <field-spec> ...<code>)</code></dt> ++ ++<h3>Macros</h3> ++<dl> ++<dt><code>(define-condition-type </code><condition-type> <supertype> <predicate> <field-spec> ...<code>)</code></dt> + <dd><p>This defines a new condition type. <Condition-type>, <supertypes>, and <predicate> must all be identifiers. <code>Define-condition-type</code> +-defines an identifier <condition-type> to some value describing +-the condition type. <supertype> must be the name of a previously +-defined condition type. </p> +-<p><code>Define-condition-type</code> also defines <predicate> to +-a predicate that identifies conditions associated with that type, or +-with any of its subtypes.</p> ++ defines an identifier <condition-type> to some value describing the condition type. <supertype> must be the name of a previously defined condition type. </p> ++<p><code>Define-condition-type</code> ++ also defines <predicate> to a predicate that identifies conditions associated with that type, or with any of its subtypes.</p> + <p>Each <field-spec> must be of the form <code>(</code> + <field> <accessor><code>)</code> + where both <field> and <accessor> must be identifiers. <code>Define-condition-type</code> +-defines each <accessor> to a procedure which extracts the value +-of the named field from a condition associated with this condition type.</p> ++ defines each <accessor> to a procedure which extracts the value of the named field from a condition associated with this condition type.</p> + </dd> + <dt><code>(condition </code><type-field-binding> ...<code>)</code></dt> + <dd><p>This creates a condition value. Each <type-field-binding> must be of the form <code>(</code> +@@ -173,9 +176,7 @@ of the named field from a condition associated with this condition type.</p> + Each <field-binding> must be of the form <code>(</code> + <field> <exp><code>)</code> + where <field> is a field identifier from the definition of <condition-type>. </p> +-<p>The <exp> are evaluated in some unspecified order; their +-values can later be extracted from the condition object via the +-accessors of the associated condition types or their supertypes.</p> ++<p>The <exp> are evaluated in some unspecified order; their values can later be extracted from the condition object via the accessors of the associated condition types or their supertypes.</p> + <p>The condition returned by <code>condition</code> + is created by a call of form</p> + <pre>(make-compound-condition +@@ -184,47 +185,47 @@ accessors of the associated condition types or their supertypes.</p> + <p> with the condition types retaining their order from the<code>condition</code> + form. The field names and values are duplicated as necessary as described below.</p> + <p>Each <type-field-binding> must contain field bindings for <em>all</em> +-fields of <condition-type> without duplicates. There is an +-exception to this rule: if a field binding is missing, and the field +-belongs to a supertype shared with one of the other +-<type-field-binding> subforms, then the value defaults to that of +-the first such binding in the <code>condition</code> ++ fields of <condition-type> without duplicates. There is an exception to this rule: if a field binding is missing, and the field belongs to a supertype shared with one of the other <type-field-binding> subforms, then the value defaults to that of the first such binding in the <code>condition</code> + form.</p> + </dd> + </dl> +-<h2>Standard Conditions</h2> +-<dl><dt><code>&condition</code> ++ ++<h3>Standard Conditions</h3> ++<dl> ++<dt><code>&condition</code> + </dt> + <dd><p>This is the root of the entire condition type hierarchy. It has a no fields.</p> + </dd> + <dt><code>&message</code> + </dt> +-<dd><p>This condition type could be defined by</p><pre>(define-condition-type &message &condition ++<dd><p>This condition type could be defined by</p> ++<pre>(define-condition-type &message &condition + message-condition? + (message condition-message)) +-</pre><p></p> ++</pre> + <p>It carries a message further describing the nature of the condition to humans.</p> + </dd> + <dt><code>&serious</code> + </dt> +-<dd><p>This condition type could be defined by</p><pre>(define-condition-type &serious &condition ++<dd><p>This condition type could be defined by</p> ++<pre>(define-condition-type &serious &condition + serious-condition?) +-</pre><p></p> +-<p>This type describes conditions serious enough that they cannot +-safely be ignored. This condition type is primarily intended as a +-supertype of other condition types.</p> +-</dd><dt><code>&error</code> ++</pre> ++<p>This type describes conditions serious enough that they cannot safely be ignored. This condition type is primarily intended as a supertype of other condition types.</p> ++</dd> ++<dt><code>&error</code> + </dt> +-<dd><p>This condition type could be defined by</p><pre>(define-condition-type &error &serious ++<dd><p>This condition type could be defined by ++</p> ++<pre>(define-condition-type &error &serious + error?) +-</pre><p></p> +-<p>This condition describes errors, typically caused by something that +-has gone wrong in the interaction of the program with the external +-world or the user.</p> ++</pre> ++<p>This condition describes errors, typically caused by something that has gone wrong in the interaction of the program with the external world or the user.</p> + </dd> +- + </dl> +-<h1>Examples</h1> ++ ++ ++<h2>Examples</h2> + <pre>(define-condition-type &c &condition + c? + (x c-x)) +@@ -284,10 +285,11 @@ world or the user.</p> + (c-x v5) => "V2" + (c1-a v5) => "a3" + (c2-b v5) => "b2" +-</pre><h1>Reference Implementation</h1> +-<p>The reference implementation makes use of <a href="http://srfi.schemers.org/srfi-1/">SRFI 1</a> +- ("List Library"), <a href="http://srfi.schemers.org/srfi-9/">SRFI 9</a> +- ("Defining Record Types"), and <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> ++</pre> ++<h2>Reference Implementation</h2> ++<p>The reference implementation makes use of <a href="srfi-1.html">SRFI 1</a> ++ ("List Library"), <a href="srfi-9.html">SRFI 9</a> ++ ("Defining Record Types"), and <a href="srfi-23.html">SRFI 23</a> + ("Error reporting mechanism").</p> + <pre>(define-record-type :condition-type + (really-make-condition-type name supertype fields all-fields) +@@ -463,15 +465,16 @@ world or the user.</p> + + (define-condition-type &error &serious + error?) +-</pre><h1>References</h1> +-<ul><li><a href="http://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> ++</pre> ++<h2>References</h2> ++<ul><li><a href="https://srfi.schemers.org/srfi-12/">SRFI 12: Exception Handling</a> + by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley</li> + <li><a href="http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1996/msg00022.html">Richard Kelsey's 1996 proposal</a> + </li> +-<li><a href="http://world.std.com/%7Epitman/Papers/Condition-Handling-2001.html">Kent Pitman's history paper</a> ++<li><a href="http://world.std.com/~pitman/Papers/Condition-Handling-2001.html">Kent Pitman's history paper</a> + </li> +-<li>The <a href="http://www.xanalys.com/software_tools/reference/HyperSpec/Body/09_.htm">Conditions chapter</a> +- from the <a href="http://www.xanalys.com/software_tools/reference/HyperSpec/Front/index.htm">Common Lisp HyperSpec</a> ++<li>The <a href="http://www.lispworks.com/documentation/HyperSpec/Body/09_.htm">Conditions chapter</a> ++ from the <a href="http://www.lispworks.com/documentation/HyperSpec/Front/index.htm">Common Lisp HyperSpec</a> + </li> + <li>The Conditions chapter by Kent M. Pitman in <a href="http://www-2.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/cltl2.html"><i>Common Lisp the Language, 2nd edition</i> + </a> +@@ -481,7 +484,7 @@ by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley</li> + </li> + </ul> + +-<h1>Copyright</h1> ++<h2>Copyright</h2> + + <p>Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights + Reserved.</p> +@@ -509,7 +512,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> ++ <hr /> + <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> +- + </body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html +index 378fbd2..535754c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-38.html +@@ -1,61 +1,74 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-38 ┃ ++┃ Commit: 0f4e3c6b6ae31cee40b48d2656960dd822bc4ad8 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 38: External Representation for Data With Shared Structure</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 38: External Representation for Data With Shared Structure</h1> + +-External Representation for Data With Shared Structure ++<p>by Ray Dillinger</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 38 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-38/srfi-38.html">https://srfi.schemers.org/srfi-38/srfi-38.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Ray Dillinger ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+38+at+srfi+dotschemers+dot+org">srfi-38@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-38">archive</a>.</p> ++<ul> ++ <li>Draft: 2002-12-20--2003-04-02</li> ++ <li>Final: 2003-04-02</li> ++</ul> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-38/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +-<UL> +- <LI>Draft: 2002/12/20-2003/04/02</li> +- <LI>Final: 2003/04/02</LI> +-</UL> +- +-<H1>Abstract</H1> +-<P> ++<h2>Abstract</h2> ++<p> + This SRFI proposes <tt>(write-with-shared-structure)</tt> and + <tt>(read-with-shared-structure)</tt>, procedures for writing + and reading external representations of data containing shared + structure. These procedures implement a proposed standard + external notation for data containing shared structure. +-</P> +-<P> ++</p> ++<p> + This SRFI permits but does not require replacing the standard + <tt>(write)</tt> and <tt>(read)</tt> functions. These functions + may be implemented without the overhead in time and space required + to detect and specify shared structure. +-</P> +-<P> ++</p> ++<p> + An implementation conforms to this SRFI if it provides procedures + named <tt>(write-with-shared-structure)</tt> and + <tt>(read-with-shared-structure)</tt>, which produce and read + the same notation as produced by the reference implementation. + It may also provide <tt>(read/ss)</tt> and <tt>(write/ss)</tt>, + equivalent functions with shorter names. +-</P> ++</p> + + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + +-<P> ++<p> + + R5RS scheme and IEEE scheme provide the procedure <tt>(write)</tt>, + which prints machine-readable representations of lists and other +@@ -65,8 +78,8 @@ case of self-referential objects the behavior of <tt>(write)</tt> + itself is undefined; it is permitted to go into an infinite loop or + invoke the dreaded curse of the nasal demons. + +-</P> +-<P> ++</p> ++<p> + + For example, it is possible to have a list within which two or more + members are the same string (in the sense of <tt>(eq?)</tt>), but when +@@ -75,17 +88,18 @@ representation to recover the <tt>(eq?)</tt> relationship. When the + list is read back in, there will be two or more copies of the string + which are <tt>(eqv?)</tt> but not <tt>(eq?)</tt>. + +-</P> +-<P> ++</p> ++<p> + As an example of the second problem, The results of evaluating +-<PRE> ++</p> ++<pre> + (begin (define a (cons 'val1 'val2)) + (set-cdr! a a) + (write a)) +-</PRE> ++</pre> + +-are undefined; in R5RS parlance, calling write on such a structure +-"is an error", but not one that is necessarily ++<p>are undefined; in R5RS parlance, calling write on such a structure ++"is an error", but not one that is necessarily + signalled. The routine is permitted to print a nonstandard notation + such as the one proposed in this standard or a different one, fail + silently, signal an error, go into an infinite loop, or make demons +@@ -95,33 +109,34 @@ problem by providing a method of writing data which is guaranteed to + be well-behaved and predictable even on data containing shared + structures. + +-</P> ++</p> + +-<P> ++<p> + + The extended functionality described below in the implementation of + <tt>(write-with-shared-structure)</tt>is already present in the + <tt>(write)</tt> function of several major scheme implementations + (PLT, SISC, Chez, Bigloo, MIT scheme, and possibly others). + +-</P> ++</p> + +-<H1>Specification</H1> +-<P> ++<h2>Specification</h2> + + <h2> Formal Grammar of the New External Representation</h2> ++<p> + This SRFI creates an alternative external representation for data + written and read under <tt>(write/ss)</tt> and <tt>(read/ss)</tt>. + It is identical to the grammar for external representation for data + written and read under <tt>(write)</tt> and <tt>(read)</tt> given in + section 7 of R5RS, except that the single production +-<PRE> ++</p> ++<pre> + + <datum> --> <simple datum> | <compound datum> + +-</PRE> +-Is replaced by the following five productions. +-<PRE> ++</pre> ++<p>Is replaced by the following five productions.</p> ++<pre> + + <datum> --> <defining datum> | <nondefining datum> | <defined datum> + +@@ -132,26 +147,25 @@ Is replaced by the following five productions. + <nondefining datum> --> <simple datum> | <compound datum> + + <indexnum> --> <digit 10>+ +-</PRE> +-</P> ++</pre> + + <h2>New Procedures</h2> +-<P> +-<PRE> + +-[[library procedure]] <a name="write-with-shared-structure">(write-with-shared-structure obj)</a> ++<pre id="write-with-shared-structure"> ++ ++[[library procedure]] (write-with-shared-structure obj) + [[library procedure]] (write-with-shared-structure obj port) + [[library procedure]] (write-with-shared-structure obj port optarg) + +-</PRE> +- ++</pre> ++<p> + Writes a written representation of obj to the given port. Strings that + appear in the written representation are enclosed in doublequotes, and + within those strings backslash and doublequote characters are escaped + by backslashes. Character objects are written using the #\ + notation. + +-</P><P> ++</p><p> + + Objects which denote locations rather than values (cons cells, + vectors, and non-zero-length strings in R5RS scheme; also mutable +@@ -164,15 +178,15 @@ If objects which denote locations occur only once in the structure, + then <tt>(write-with-shared-structure)</tt> must produce the same + external representation for those objects as <tt>(write)</tt>. + +-</P> ++</p> + +-<P> ++<p> + + Write-with-shared-structure must terminate in finite time when writing + finite data. Write-with-shared-structure must produce a finite + representation when writing finite data. + +-</P><P> ++</p><p> + + Write-with-shared-structure returns an unspecified value. The port + argument may be omitted, in which case it defaults to the value +@@ -184,30 +198,29 @@ still write a representation that can be read by + use optarg to specify formatting conventions, numeric radixes, or + return values. The reference implementation ignores optarg. + +-</P> +-<P> ++</p> ++<p> + +-For example, the code +-<PRE> ++For example, the code</p> ++<pre> + + (begin (define a (cons 'val1 'val2)) + (set-cdr! a a) + (write-with-shared-structure a)) + +-</PRE> ++</pre> + +-should produce the output <tt> #1=(val1 . #1#) </tt>. This shows a cons ++<p>should produce the output <tt> #1=(val1 . #1#) </tt>. This shows a cons + cell whose cdr contains itself. ++</p> + +-</P><P> +- +-<PRE> ++<pre id="read-with-shared-structure"> + +-[[library procedure]] <a name="read-with-shared-structure">(read-with-shared-structure)</a> ++[[library procedure]] (read-with-shared-structure) + [[library procedure]] (read-with-shared-structure port) + +-</PRE> +- ++</pre> ++<p> + <tt>(read-with-shared-structure)</tt> converts the external + representations of Scheme objects produced by + <tt>(write-with-shared-structure)</tt> into scheme objects. That is, +@@ -217,7 +230,7 @@ external representation grammar defined above. + from the given input port, updating port to point to the first + character past the end of the external representation of the object. + +-</P> <P> ++</p> <p> + + If an end-of-file is encountered in the input before any characters + are found that can begin an object, then an end-of-file object is +@@ -228,20 +241,20 @@ the beginning of an object's external representation, but the external + representation is incomplete and therefore not parsable, an error is + signalled. + +-</P><P> ++</p><p> + + The port argument may be omitted, in which case it defaults to the + value returned by <tt>(current-input-port)</tt>. It is an error to + read from a closed port. + +-</P> ++</p> + + + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + +-<P> ++<p> + + The reference implementation of <tt>(write-with-shared-structure)</tt> + is based on an implementation provided by Al Petrofsky. If there are +@@ -251,17 +264,17 @@ for an optional port argument. The reference implementation of + provided by Al Petrofsky. Both are used here with his generous + permission. + +-</P> ++</p> + +-<P> ++<p> + + Note that portability forces the reference implementation of + <tt>(write-with-shared-structure)</tt> to be O(N^2) but that if an + implementor tracks objects through additional fields hidden from R5RS + scheme, a more efficient implementation can be provided. + +-</P> +-<P> ++</p> ++<p> + + If all the locations in your scheme are mutable and you don't do any + locking or multithreading, you can write an O(n) version that +@@ -273,10 +286,10 @@ does not give the programmer access to mutability information nor to + comparison of constant data's addresses, but both of these are trivial + operations if you have access to the system's internals. + +-</P> ++</p> + + +-<PRE> ++<pre> + ;;; A printer that shows all sharing of substructures. Uses the Common + ;;; Lisp print-circle notation: #n# refers to a previous substructure + ;;; labeled with #n=. Takes O(n^2) time. +@@ -354,7 +367,7 @@ operations if you have access to the system's internals. + (define (scan obj alist) + (cond ((not (interesting? obj)) alist) + ((assq obj alist) +- => (lambda (p) (if (cdr p) alist (acons obj #t alist)))) ++ => (lambda (p) (if (cdr p) alist (acons obj #t alist)))) + (else + (let ((alist (acons obj #f alist))) + (cond ((pair? obj) (scan (car obj) (scan (cdr obj) alist))) +@@ -406,7 +419,7 @@ operations if you have access to the system's internals. + (if (eof-object? c) + (error "EOF inside a string") + (case c +- ((#\") (list->string (reverse chars))) ++ ((#\") (list->string (reverse chars))) + ((#\\) (read-it (cons (read-char*) chars))) + (else (read-it (cons c chars)))))))) + +@@ -415,7 +428,7 @@ operations if you have access to the system's internals. + (let iter ((chars '())) + (let ((c (peek-char*))) + (if (or (eof-object? c) (not (pred c))) +- (list->string (reverse chars)) ++ (list->string (reverse chars)) + (iter (cons (read-char*) chars)))))) + + ;; reads a character after the #\ has been read. +@@ -433,11 +446,11 @@ operations if you have access to the system's internals. + (define (read-number first-char) + (let ((str (string-append (string first-char) + (read-some-chars not-delimiter?)))) +- (or (string->number str) ++ (or (string->number str) + (error "Malformed number: " str)))) + + (define char-standard-case +- (if (char=? #\a (string-ref (symbol->string 'a) 0)) ++ (if (char=? #\a (string-ref (symbol->string 'a) 0)) + char-downcase + char-upcase)) + +@@ -449,10 +462,10 @@ operations if you have access to the system's internals. + (string-set! new i (char-standard-case (string-ref str i)))))) + + (define (read-identifier) +- (string->symbol (string-standard-case (read-some-chars not-delimiter?)))) ++ (string->symbol (string-standard-case (read-some-chars not-delimiter?)))) + + (define (read-part-spec) +- (let ((n (string->number (read-some-chars char-numeric?)))) ++ (let ((n (string->number (read-some-chars char-numeric?)))) + (let ((c (read-char*))) + (case c + ((#\=) (cons 'decl n)) +@@ -525,8 +538,8 @@ operations if you have access to the system's internals. + (if (char? (car first-token)) + (case (car first-token) + ((#\() (read-list-tail)) +- ((#\#) (list->vector (read-list-tail))) +- ((#\. #\)) (error (string-append "Unexpected \"" first-token "\""))) ++ ((#\#) (list->vector (read-list-tail))) ++ ((#\. #\)) (error (string-append "Unexpected \"" (string (car first-token)) "\""))) + (else + (list (caadr (assv (car first-token) + '((#\' 'x) (#\, ,x) (#\` `x) (#\@ ,@x)))) +@@ -542,7 +555,7 @@ operations if you have access to the system's internals. + ((use) + ;; To use a part, it must have been + ;; declared before this chain started. +- (cond ((assv n starting-alist) => cdr) ++ (cond ((assv n starting-alist) => cdr) + (else (error "Use of undeclared part " n)))) + ((decl) + (if (assv n parts-alist) +@@ -596,10 +609,10 @@ operations if you have access to the system's internals. + (fill-in-parts elt)))))))) + obj)) + +-</PRE> ++</pre> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Ray Dillinger 2003. All Rights Reserved.</p> + + <p> +@@ -625,13 +638,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a +- href="mailto:srfi-editors@srfi.schemers.org">David Rush</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Rush</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Wed Apr 2 19:58:58 BST 2003 ++Last modified: Wed Jan 19 08:52:24 MET 2011 + <!-- hhmts end --> + </body> + </html> +- +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html +index efd33ed..792b2aa 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-39.html +@@ -1,69 +1,82 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-39 ┃ ++┃ Commit: 3b19ad3539d2430a484b126183671916af7a48fb ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 39: Parameter objects</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 39: Parameter objects</h1> + +-SRFI 39: Parameter objects ++<p>by Marc Feeley</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 39 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-39/srfi-39.html">https://srfi.schemers.org/srfi-39/srfi-39.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Marc Feeley ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+39+at+srfi+dotschemers+dot+org">srfi-39@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-39">archive</a>.</p> ++<ul> ++ <li>Draft: 2002-12-21--2003-02-18</li> ++ <li>Revised: 2003-05-15</li> ++ <li>Final: 2003-06-30</li> ++</ul> + +-<H1>Status</H1> + +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access +-previous messages via +-<a href="http://srfi.schemers.org/srfi-39/mail-archive/maillist.html"> +-the archive of the mailing list</a>. ++<h2>Abstract</h2> + +-<UL> +- <LI>Draft: 2002/12/21-2003/02/18</LI> +- <LI>Revised: 2003/5/15</LI> +- <LI>Final: 2003/6/30</LI> +-</UL> +- +- +-<H1>Abstract</H1> +- +-<P> +-This SRFI defines <I>parameter</I> objects, the procedure +-<CODE>make-parameter</CODE> to +-create parameter objects and the <CODE>parameterize</CODE> special ++<p> ++This SRFI defines <i>parameter</i> objects, the procedure ++<code>make-parameter</code> to ++create parameter objects and the <code>parameterize</code> special + form to dynamically bind parameter objects. In the dynamic + environment, each parameter object is bound to a cell containing the + value of the parameter. When a procedure is called the called + procedure inherits the dynamic environment from the caller. The +-<CODE>parameterize</CODE> special form allows the binding of a ++<code>parameterize</code> special form allows the binding of a + parameter object to be changed for the dynamic extent of its body. +-</P> ++</p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + +-<P> +-The <I>dynamic environment</I> is the structure which allows ++<p> ++The <i>dynamic environment</i> is the structure which allows + the system to find the value returned by the R5RS procedures +-<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE>. +-The R5RS procedures <CODE>with-input-from-file</CODE> and +-<CODE>with-output-to-file</CODE> extend the dynamic environment to ++<code>current-input-port</code> and <code>current-output-port</code>. ++The R5RS procedures <code>with-input-from-file</code> and ++<code>with-output-to-file</code> extend the dynamic environment to + produce a new dynamic environment which is in effect for the dynamic + extent of the call to the thunk passed as their last argument. These + procedures are essentially special purpose dynamic binding operations +-on hidden dynamic variables (one for <CODE>current-input-port</CODE> +-and one for <CODE>current-output-port</CODE>). The purpose of this ++on hidden dynamic variables (one for <code>current-input-port</code> ++and one for <code>current-output-port</code>). The purpose of this + SRFI is to generalize this dynamic binding mechanism (which exists in + all R5RS compliant systems) to allow the user to introduce new dynamic + variables and dynamically bind them. +-</P> ++</p> + +-<P> ++<p> + General dynamic binding mechanisms exist in several implementations of + Scheme under various names, including "fluid" variables and parameter + objects. The parameter objects specified in this SRFI are compatible +@@ -72,9 +85,9 @@ currently support parameter objects (in the sense that it is possible + to implement this SRFI so that old code works the same as before). We + believe Chez-Scheme was the first implementation of Scheme to have + used parameter objects. +-</P> ++</p> + +-<P> ++<p> + In the presence of threads, the dynamic binding mechanism does not + behave the same way in all implementations of Scheme supporting + dynamic binding. The issue is the relationship between the dynamic +@@ -92,105 +105,105 @@ environment share the same cells (i.e. an assignment of a value to a + dynamic variable is visible in the other thread). Note that in the + absence of assignment to dynamic variables the MzScheme and Gambit-C + approaches are equivalent. +-</P> ++</p> + +-<P> ++<p> + Given that there are semantic differences in the presence of threads + and that there are valid reasons for choosing each semantics, this + SRFI does not specify the semantics of parameter objects in the + presence of threads. It is left to the implementation and other SRFIs + which extend this SRFI to specify the interaction between parameter + objects and threads. +-</P> ++</p> + +-<H1>Specification</H1> ++<h2>Specification</h2> + +-<P> +-The <I>dynamic environment</I> is composed of two parts: the <I>local +-dynamic environment</I> and the <I>global dynamic environment</I>. ++<p> ++The <i>dynamic environment</i> is composed of two parts: the <i>local ++dynamic environment</i> and the <i>global dynamic environment</i>. + The global dynamic environment is used to lookup parameter objects + that can't be found in the local dynamic environment. When parameter + objects are created, their initial binding is put in the global + dynamic environment (by mutation). The local dynamic environment is +-only extended by the <CODE>parameterize</CODE> form. +-</P> +- +-<P> +-<I>Parameter objects</I> are created with the +-<CODE>make-parameter</CODE> procedure which takes one or two +-arguments. The second argument is a one argument <I>conversion +-procedure</I>. If only one argument is passed to +-<CODE>make-parameter</CODE> the identity function is used as a ++only extended by the <code>parameterize</code> form. ++</p> ++ ++<p> ++<i>Parameter objects</i> are created with the ++<code>make-parameter</code> procedure which takes one or two ++arguments. The second argument is a one argument <i>conversion ++procedure</i>. If only one argument is passed to ++<code>make-parameter</code> the identity function is used as a + conversion procedure. The global dynamic environment is updated to + associate the parameter object to a new cell. The initial content of + the cell is the result of applying the conversion procedure to the +-first argument of <CODE>make-parameter</CODE>. +-</P> ++first argument of <code>make-parameter</code>. ++</p> + +-<P> +-A <I>parameter object</I> is a procedure which accepts zero or one ++<p> ++A <i>parameter object</i> is a procedure which accepts zero or one + argument. The cell bound to a particular parameter object in the + dynamic environment is accessed by calling the parameter object. When + no argument is passed, the content of the cell is returned. When one + argument is passed the content of the cell is updated with the result + of applying the parameter object's conversion procedure to the + argument. +-</P> ++</p> + +-<P> +-The <CODE>parameterize</CODE> special form, when given a parameter ++<p> ++The <code>parameterize</code> special form, when given a parameter + object and a value, binds for the dynamic extent of its body the + parameter object to a new cell. The initial content of the cell is + the result of applying the parameter object's conversion procedure to +-the value. The <CODE>parameterize</CODE> special form behaves +-analogously to <CODE>let</CODE> when binding more than one parameter ++the value. The <code>parameterize</code> special form behaves ++analogously to <code>let</code> when binding more than one parameter + object (that is the order of evaluation is unspecified and the new +-bindings are only visible in the body of the <CODE>parameterize</CODE> ++bindings are only visible in the body of the <code>parameterize</code> + special form). +-</P> ++</p> + +-<P> ++<p> + Note that the conversion procedure can be used for guaranteeing the + type of the parameter object's binding and/or to perform some + conversion of the value. +-</P> ++</p> + +-<P> ++<p> + Because it is possible to implement the R5RS procedures +-<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE> ++<code>current-input-port</code> and <code>current-output-port</code> + as parameter objects and this offers added functionnality, it is + required by this SRFI that they be implemented as parameter objects +-created with <CODE>make-parameter</CODE>. +-</P> ++created with <code>make-parameter</code>. ++</p> + +-<H4>Procedures and syntax</H4> ++<h4>Procedures and syntax</h4> + +-<DL> ++<dl> + +-<DT><PRE> +-<a name="make-parameter">(make-parameter <I>init</I> [<I>converter</I>])</a> ;procedure +-</PRE><DD> ++<dt id="make-parameter"><pre> ++(make-parameter <i>init</i> [<i>converter</i>]) ;procedure ++</pre></dt><dd> + +-<P> ++<p> + Returns a new parameter object which is bound in the global dynamic + environment to a cell containing the value returned by the call +-<CODE>(<I>converter</I> <I>init</I>)</CODE>. If the conversion +-procedure <I>converter</I> is not specified the identity function is ++<code>(<i>converter</i> <i>init</i>)</code>. If the conversion ++procedure <i>converter</i> is not specified the identity function is + used instead. +-</P> ++</p> + +-<P> ++<p> + The parameter object is a procedure which accepts zero or one + argument. When it is called with no argument, the content of the cell + bound to this parameter object in the current dynamic environment is + returned. When it is called with one argument, the content of the + cell bound to this parameter object in the current dynamic environment +-is set to the result of the call <CODE>(<I>converter</I> +-<I>arg</I>)</CODE>, where <I>arg</I> is the argument passed to the ++is set to the result of the call <code>(<i>converter</i> ++<i>arg</i>)</code>, where <i>arg</i> is the argument passed to the + parameter object, and an unspecified value is returned. +-</P> ++</p> + +-<PRE> ++<pre> + (define radix + (make-parameter 10)) + +@@ -202,9 +215,9 @@ parameter object, and an unspecified value is returned. + x + (error "only booleans are accepted by write-shared"))))) + +- (radix) ==> 10 ++ (radix) ==> 10 + (radix 2) +- (radix) ==> 2 ++ (radix) ==> 2 + (write-shared 0) gives an error + + (define prompt +@@ -215,58 +228,61 @@ parameter object, and an unspecified value is returned. + x + (with-output-to-string (lambda () (write x))))))) + +- (prompt) ==> "123" +- (prompt ">") +- (prompt) ==> ">" +-</PRE> +- +-<P> +-<DT><PRE> +-<a name="parameterize">(parameterize ((<I>expr1</I> <I>expr2</I>) ...) <I><body></I>)</a> ;syntax +-</PRE><DD> ++ (prompt) ==> "123" ++ (prompt ">") ++ (prompt) ==> ">" ++</pre> ++</dd> ++<dt id="parameterize"><pre> ++(parameterize ((<i>expr1</i> <i>expr2</i>) ...) <i><body></i>) ;syntax ++</pre> ++</dt> ++<dd> + +-<P> +- The expressions <I>expr1</I> and <I>expr2</I> are evaluated in an +- unspecified order. The value of the <I>expr1</I> expressions must +- be parameter objects. For each <I>expr1</I> expression and in an ++<p> ++ The expressions <i>expr1</i> and <i>expr2</i> are evaluated in an ++ unspecified order. The value of the <i>expr1</i> expressions must ++ be parameter objects. For each <i>expr1</i> expression and in an + unspecified order, the local dynamic environment is extended with +- a binding of the parameter object <I>expr1</I> to a new cell whose +- content is the result of the call <CODE>(<I>converter</I> +- <I>val</I>)</CODE>, where <I>val</I> is the value of <I>expr2</I> +- and <I>converter</I> is the conversion procedure of the parameter ++ a binding of the parameter object <i>expr1</i> to a new cell whose ++ content is the result of the call <code>(<i>converter</i> ++ <i>val</i>)</code>, where <i>val</i> is the value of <i>expr2</i> ++ and <i>converter</i> is the conversion procedure of the parameter + object. The resulting dynamic environment is then used for the +- evaluation of <I><body></I> (which refers to the R5RS grammar ++ evaluation of <i><body></i> (which refers to the R5RS grammar + nonterminal of that name). The result(s) of the +- <CODE>parameterize</CODE> form are the result(s) of the +- <I><body></I>. +-</P> ++ <code>parameterize</code> form are the result(s) of the ++ <i><body></i>. ++</p> + +-<PRE> +- (radix) ==> 2 +- (parameterize ((radix 16)) (radix)) ==> 16 +- (radix) ==> 2 ++<pre> ++ (radix) ==> 2 ++ (parameterize ((radix 16)) (radix)) ==> 16 ++ (radix) ==> 2 + +- (define (f n) (number->string n (radix))) ++ (define (f n) (number->string n (radix))) + +- (f 10) ==> "1010" +- (parameterize ((radix 8)) (f 10)) ==> "12" +- (parameterize ((radix 8) (prompt (f 10))) (prompt)) ==> "1010" +-</PRE> ++ (f 10) ==> "1010" ++ (parameterize ((radix 8)) (f 10)) ==> "12" ++ (parameterize ((radix 8) (prompt (f 10))) (prompt)) ==> "1010" ++</pre> ++</dd> ++</dl> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + +-<P> ++<p> + The following implementation uses association lists to represent local + dynamic environments. The global dynamic environment binding is + stored in the parameter object itself. Since we are assuming that + there is a single thread, the current local dynamic environment can be +-bound to a global variable, <CODE>dynamic-env-local</CODE>. Mutations +-of this variable are wrapped in a <CODE>dynamic-wind</CODE> so that ++bound to a global variable, <code>dynamic-env-local</code>. Mutations ++of this variable are wrapped in a <code>dynamic-wind</code> so that + the local dynamic environment returns to its previous value when +-control exits the body of the <CODE>parameterize</CODE>. +-</P> ++control exits the body of the <code>parameterize</code>. ++</p> + +-<PRE> ++<pre> + (define make-parameter + (lambda (init . conv) + (let ((converter +@@ -320,9 +336,9 @@ control exits the body of the <CODE>parameterize</CODE>. + + (define dynamic-env-local-set! + (lambda (new-env) (set! dynamic-env-local new-env))) +-</PRE> ++</pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Marc Feeley 2002. All Rights Reserved.</p> + + <p> +@@ -349,7 +365,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html +index f48174f..d11a35a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-4.html +@@ -1,34 +1,51 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-4 ┃ ++┃ Commit: 509cbf1158de7a7236036bb5404673791fb2b40e ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 4: Homogeneous numeric vector datatypes</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 4: Homogeneous numeric vector datatypes</h1> + +-SRFI-4: Homogeneous numeric vector datatypes ++<p>by Marc Feeley</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 4 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-4/srfi-4.html">https://srfi.schemers.org/srfi-4/srfi-4.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Marc Feeley +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <A +-HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access previous messages via <A +-HREF="http://srfi.schemers.org/srfi-4/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1998/1/11 +-<LI>Draft: 1999/1/19-1999/03/19 +-<LI>Revised: 1999/04/26 +-<LI>Final: 1999/5/22 +-</UL> +- +-<H1>Abstract</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+4+at+srfi+dotschemers+dot+org">srfi-4@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-4">archive</a>.</p> ++<ul> ++ <li>Received: 1998-01-11</li> ++ <li>Draft: 1999-01-19--1999-03-19</li> ++ <li>Revised: 1999-04-26</li> ++ <li>Final: 1999-05-22</li> ++</ul> + ++<h2>Abstract</h2> ++<p> + This SRFI describes a set of datatypes for vectors whose elements are + of the same numeric type (signed or unsigned exact integer or inexact + real of a given precision). These datatypes support operations +@@ -37,9 +54,9 @@ An external representation is specified which must be supported by the + <code>read</code> and <code>write</code> procedures and by the program + parser (i.e. programs can contain references to literal homogeneous + vectors). +- +-<H1>Rationale</H1> +- ++</p> ++<h2>Rationale</h2> ++<p> + Like lists, Scheme vectors are a heterogeneous datatype which impose + no restriction on the type of the elements. This generality is not + needed for applications where all the elements are of the same type. +@@ -51,76 +68,74 @@ Moreover, homogeneous vectors are convenient for interfacing with + low-level libraries (e.g. binary block I/O) and to interface with + foreign languages which support homogeneous vectors. Finally, the use + of homogeneous vectors allows certain errors to be caught earlier. +- +- <p></p> +- ++</p> ++<p> + This SRFI specifies a set of homogeneous vector datatypes which cover + the most practical case, that is where the type of the elements is + numeric (exact integer or inexact real) and the precision and + representation is efficiently implemented on the hardware of most + current computer architectures (8, 16, 32 and 64 bit integers, either + signed or unsigned, and 32 and 64 bit floating point numbers). ++</p> + +-<H1>Specification</H1> +- ++<h2>Specification</h2> ++<p> + There are 8 datatypes of exact integer homogeneous vectors (which will + be called integer vectors): ++</p> ++<table> ++<tr> ++<td></td><td><strong>datatype</strong> </td><td><strong>type of elements</strong> ++</td></tr> ++<tr id="s8vector"> ++<td></td><td><code>s8vector</code> </td><td>signed exact integer in the range -(2^7) to (2^7)-1 ++</td></tr> ++<tr id="u8vector"> ++<td></td><td><code>u8vector</code> </td><td>unsigned exact integer in the range 0 to (2^8)-1 ++</td></tr> ++<tr id="s16vector"> ++<td></td><td><code>s16vector</code></td><td>signed exact integer in the range -(2^15) to (2^15)-1 ++</td></tr> ++<tr id="u16vector"> ++<td></td><td><code>u16vector</code></td><td>unsigned exact integer in the range 0 to (2^16)-1 ++</td></tr> ++<tr id="s32vector"> ++<td></td><td><code>s32vector</code></td><td>signed exact integer in the range -(2^31) to (2^31)-1 ++</td></tr> ++<tr id="u32vector"> ++<td></td><td><code>u32vector</code></td><td>unsigned exact integer in the range 0 to (2^32)-1 ++</td></tr> ++<tr id="s64vector"> ++<td></td><td><code>s64vector</code></td><td>signed exact integer in the range -(2^63) to (2^63)-1 ++</td></tr> ++<tr id="u64vector"> ++<td></td><td><code>u64vector</code></td><td>unsigned exact integer in the range 0 to (2^64)-1 ++</td></tr> ++</table> + +-<TABLE> +-<TR> +-<TD><TD><STRONG>datatype</STRONG> <TD><STRONG>type of elements</STRONG> +-</TR> +-<TR> +-<TD><TD><code><a name="s8vector">s8vector</a></code> <TD>signed exact integer in the range -(2^7) to (2^7)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="u8vector">u8vector</a></code> <TD>unsigned exact integer in the range 0 to (2^8)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="s16vector">s16vector</a></code><TD>signed exact integer in the range -(2^15) to (2^15)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="u16vector">u16vector</a></code><TD>unsigned exact integer in the range 0 to (2^16)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="s32vector">s32vector</a></code><TD>signed exact integer in the range -(2^31) to (2^31)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="u32vector">u32vector</a></code><TD>unsigned exact integer in the range 0 to (2^32)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="s64vector">s64vector</a></code><TD>signed exact integer in the range -(2^63) to (2^63)-1 +-</TR> +-<TR> +-<TD><TD><code><a name="u64vector">u64vector</a></code><TD>unsigned exact integer in the range 0 to (2^64)-1 +-</TR> +-</TABLE> +- +- <p></p> +- ++<p> + There are 2 datatypes of inexact real homogeneous vectors (which will + be called float vectors): ++</p> + +-<TABLE> +-<TR> +-<TD><TD><STRONG>datatype</STRONG> <TD><STRONG>type of elements</STRONG> +-</TR> +-<TR> +-<TD><TD><code><a name="f32vector">f32vector</a></code> <TD>inexact real +-</TR> +-<TR> +-<TD><TD><code><a name="f64vector">f64vector</a></code> <TD>inexact real +-</TR> +-</TABLE> +- +- <p></p> ++<table> ++<tr> ++<td></td><td><strong>datatype</strong> </td><td><strong>type of elements</strong> ++</td></tr> ++<tr id="f32vector"> ++<td></td><td><code>f32vector</code> </td><td>inexact real ++</td></tr> ++<tr id="f64vector"> ++<td></td><td><code>f64vector</code> </td><td>inexact real ++</td></tr> ++</table> + ++<p> + The only difference between the two float vector types is that + <code>f64vector</code>s preserve at least as much precision as + <code>f32vector</code>s (see the implementation section for details). +- +- <p></p> +- ++</p> ++<p> + A Scheme system that conforms to this SRFI does not have to support + all of these homogeneous vector datatypes. However, a Scheme system + must support <code>f32vector</code>s and <code>f64vector</code>s if it +@@ -138,17 +153,15 @@ the Scheme system supports by calling the + <code>string->number</code> procedure (e.g. + <code>(string->number "0.0")</code> returns <code>#f</code> if the + Scheme system does not support inexact reals). +- +- <p></p> +- ++</p> ++<p> + Each homogeneous vector datatype has an external representation which + is supported by the <code>read</code> and <code>write</code> + procedures and by the program parser. Each datatype also has a set of + associated predefined procedures analogous to those available for + Scheme's heterogeneous vectors. +- +- <p></p> +- ++</p> ++<p> + For each value of <code>TAG</code> in { + <code>s8</code>, <code>u8</code>, + <code>s16</code>, <code>u16</code>, +@@ -156,30 +169,27 @@ For each value of <code>TAG</code> in { + <code>s64</code>, <code>u64</code>, + <code>f32</code>, <code>f64</code> + }, if the datatype <code>TAGvector</code> is supported, then ++</p> + +- <p></p> +- +-<OL> +- +-<LI> the external representation of instances of the datatype ++<ol> ++ <li> ++ <p> ++ the external representation of instances of the datatype + <code>TAGvector</code> is <code>#TAG(</code> ...elements... <code>)</code>. +- +- <p></p> +- ++ </p> ++ <p> + For example, <code>#u8(0 #e1e2 #xff)</code> is an + <code>u8vector</code> of length 3 containing 0, 100 and 255; + <code>#f64(-1.5)</code> is an <code>f64vector</code> of length 1 + containing -1.5. +- +- <p></p> +- ++ </p> ++ <p> + Note that the syntax for float vectors conflicts with Standard Scheme + which parses <code>#f32()</code> as 3 objects: <code>#f</code>, + <code>32</code> and <code>()</code>. For this reason, conformance to + this SRFI implies this minor nonconformance to Standard Scheme. +- +- <p></p> +- ++ </p> ++ <p> + This external representation is also available in program source code. + For example, <code>(set! x '#u8(1 2 3))</code> will set <code>x</code> + to the object <code>#u8(1 2 3)</code>. Literal homogeneous vectors +@@ -189,22 +199,23 @@ vectors can appear in quasiquotations but must not contain + (i.e. <code>`(,x #u8(1 2))</code> is legal but <code>`#u8(1 ,x + 2)</code> is not). This restriction is to accommodate the many Scheme + systems that use the <code>read</code> procedure to parse programs. +- +- <p></p> +- +-<LI> the following predefined procedures are available: +- +-<OL> +-<LI> <code>(TAGvector? obj)</code> +-<LI> <code>(make-TAGvector n [ TAGvalue ])</code> +-<LI> <code>(TAGvector TAGvalue...)</code> +-<LI> <code>(TAGvector-length TAGvect)</code> +-<LI> <code>(TAGvector-ref TAGvect i)</code> +-<LI> <code>(TAGvector-set! TAGvect i TAGvalue)</code> +-<LI> <code>(TAGvector->list TAGvect)</code> +-<LI> <code>(list->TAGvector TAGlist)</code> +-</OL> +- ++ </p> ++ </li> ++ <li> ++ <p> ++ the following predefined procedures are available: ++ </p> ++ <ol> ++ <li> <code>(TAGvector? obj)</code></li> ++ <li> <code>(make-TAGvector n [ TAGvalue ])</code></li> ++ <li> <code>(TAGvector TAGvalue...)</code></li> ++ <li> <code>(TAGvector-length TAGvect)</code></li> ++ <li> <code>(TAGvector-ref TAGvect i)</code></li> ++ <li> <code>(TAGvector-set! TAGvect i TAGvalue)</code></li> ++ <li> <code>(TAGvector->list TAGvect)</code></li> ++ <li> <code>(list->TAGvector TAGlist)</code></li> ++ </ol> ++ <p> + where <code>obj</code> is any Scheme object, <code>n</code> is a + nonnegative exact integer, <code>i</code> is a nonnegative exact + integer less than the length of the vector, <code>TAGvect</code> is an +@@ -213,41 +224,40 @@ is a number of the type acceptable for elements of the + <code>TAGvector</code> datatype, and <code>TAGlist</code> is a proper + list of numbers of the type acceptable for elements of the + <code>TAGvector</code> datatype. +- +- <p></p> +- ++ </p> ++ <p> + It is an error if <code>TAGvalue</code> is not the same type as the + elements of the <code>TAGvector</code> datatype (for example if an + exact integer is passed to <code>f64vector</code>). If the fill + value is not specified, the content of the vector is unspecified + but individual elements of the vector are guaranteed to be in the + range of values permitted for that type of vector. ++ </p> ++ </li> ++</ol> + +-</OL> +- +-<H1>Implementation</H1> +- ++<h2>Implementation</h2> ++<p> + The homogeneous vector datatypes described here suggest a concrete + implementation as a sequence of 8, 16, 32 or 64 bit elements, using + two's complement representation for the signed exact integers, and + single and double precision IEEE-754 floating point representation for + the inexact reals. Although this is a practical implementation on +-many modern byte addressed machines, a different implementation is ++many modern byte-addressed machines, a different implementation is + possible for machines which don't support these concrete numeric types + (the CRAY-T90 for example does not have a 32 bit floating point + representation and the 64 bit floating point representation does not + conform to IEEE-754, so both the <code>f32vector</code> and + <code>f64vector</code> datatypes could be represented the same way + with 64 bit floating point numbers). +- +- <p></p> +- ++</p> ++<p> + A portable implementation of the homogeneous vector predefined + procedures can be based on Scheme's heterogeneous vectors. + Here is for example an implementation of <code>s8vector</code>s + which is exempt of error checking: +- +-<PRE> ++</p> ++<pre> + (define s8vector? #f) + (define make-s8vector #f) + (define s8vector #f) +@@ -318,10 +328,8 @@ which is exempt of error checking: + (and (orig-vector? obj) + (orig-not (and (orig-> (orig-vector-length obj) 0) + (orig-eq? (orig-vector-ref obj 0) tag))))))) +-</PRE> +- +- <p></p> +- ++</pre> ++<p> + The Scheme system's <code>read</code> and <code>write</code> + procedures and the program parser also need to be extended to handle + the homogeneous vector external representations. The implementation +@@ -333,9 +341,12 @@ is the case, parse a symbol and check if it is <code>t</code>, + <code>f</code>, <code>s8</code>, <code>f32</code>, and so on, and in + the case of a homogeneous vector prefix, check if the next character + is an opening parenthesis). ++</p> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> ++<p> + Copyright (C) Marc Feeley (1999). All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -360,8 +371,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +-<hr> +-<address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org"> ++<hr /> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org"> + Shriram Krishnamurthi</a></address> + + </body> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html +index 7340781..0d0300c 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-40.html +@@ -1,46 +1,67 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-40 ┃ ++┃ Commit: b844744685db101a43dfa6e52a4143a0bc1c2663 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 40: A Library of Streams</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 40: A Library of Streams</h1> + +-SRFI 40: A Library of Streams ++<p>by Philip L. Bewig</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 40 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-40/srfi-40.html">https://srfi.schemers.org/srfi-40/srfi-40.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Philip L. Bewig ++<p>This SRFI is currently in <em>withdrawn</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+40+at+srfi+dotschemers+dot+org">srfi-40@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-40">archive</a>.</p> ++<ul> ++ <li> ++ Received: <a href="https://srfi.schemers.org/srfi-40/srfi-40-1.1.txt">2003-02-03</a> ++ </li> ++ <li> ++ Draft: 2003-02-03--2003-04-03 ++ </li> ++ <li> ++ Revised: <a href="https://srfi.schemers.org/srfi-40/srfi-40-1.2.txt">2003-08-02</a> ++ </li> ++ <li> ++ Revised: <a href="https://srfi.schemers.org/srfi-40/srfi-40-1.3.txt">2003-12-23</a> ++ </li> ++ <li> ++ Final: <a href="">2004-08-22</a> ++ </li> ++ <li> ++ Withdrawn (superseded by ++ <a href="srfi-41/srfi-41.html">SRFI 41</a>): ++ 2017-08-10 ++ </li> ++</ul> + +-<H1>Status</H1> + +-<p> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-To comments +-this SRFI, please mail to +-<a href="mailto:srfi-40@srfi.schemers.org"> +-<code>srfi-40@srfi.schemers.org</code></a>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html"> +-instructions here</a> to subscribe to the list. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-40/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-40/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-</P> +- +-<LI>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-40/srfi-40.txt?rev=1.1">2003/02/03</a> +-<LI>Draft: 2003/02/03-2003/04/03 +-<LI>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-40/srfi-40.txt?rev=1.2">2003/08/02</a> +-<LI>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-40/srfi-40.txt?rev=1.3">2003/12/23</a> +-<LI>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-40/srfi-40.html?rev=1.4">2004/08/22</a> +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + <p> + Along with higher-order functions, one of the hallmarks of functional +@@ -69,7 +90,7 @@ convenient processing of streams and shows several examples of their + use. + </p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p> + Two of the defining characteristics of functional programming +@@ -90,17 +111,16 @@ programming with streams. + + <p> + Scheme has a long tradition of computing with streams. The great +-computer science textbook <a href="srfi-40.html#sicp">Structure and Interpretation ++computer science textbook <a href="#sicp">Structure and Interpretation + of Computer Programs</a>, uses streams extensively. +-The <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-13.html#%_chap_Temp_9">example</a> given ++The <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-13.html#%25_chap_Temp_9">example</a> given + in R5RS makes use of streams to integrate systems of differential + equations using the method of Runge-Kutta. MIT Scheme, the original +-implementation of Scheme, provides streams natively. <a +-href="srfi-40.html#scheme-and-the-art">Scheme and the Art of Programming</a>, ++implementation of Scheme, provides streams natively. <a href="#scheme-and-the-art">Scheme and the Art of Programming</a>, + discusses streams. + Some Scheme-like languages also have traditions of using streams: +-Winston and Horn, in their classic <a href="srfi-40.html#lisp">Lisp textbook</a>, discuss streams, and +-so does Larry Paulson in his <a href="srfi-40.html#ml-working-programmer">text on ++Winston and Horn, in their classic <a href="#lisp">Lisp textbook</a>, discuss streams, and ++so does Larry Paulson in his <a href="#ml-working-programmer">text on + ML</a>. Streams are an important and useful data structure. + </p> + +@@ -128,8 +148,7 @@ operational difference between the two types of streams. + </p> + + <p> +-Philip Wadler, Walid Taha, and David MacQueen, in their paper <a +-href="srfi-40.html#laziness-even-odd">"How to add laziness to a strict language ++Philip Wadler, Walid Taha, and David MacQueen, in their paper <a href="#laziness-even-odd">"How to add laziness to a strict language + without even being odd"</a>, describe how they added streams to the + SML/NJ compiler. They discuss two kinds of streams: odd streams, as + in SICP et al, and even streams, as in Haskell; the names odd and even +@@ -180,7 +199,7 @@ Here are the first two figures from their paper, rewritten in Scheme: + (cutoff1 (- n 1) + (cdr1 strm)))))) + </pre></td> +-<td valign=top> ++<td valign="top"> + <pre>;;; FIGURE 2 -- EVEN + + (define nil2 (delay '())) +@@ -259,7 +278,7 @@ and even streams. We expect the two constructors <code>nil</code> and + <code>nil</code> and <code>cons</code> return a strict list, but the + even <code>nil</code> and <code>cons</code> return promises. + <code>Nil?</code>, <code>car</code> and <code>cdr</code> change to +-accommodate the underlying representation differences. ++accomodate the underlying representation differences. + <code>Cutoff</code> is identical in the two versions, because it + doesn't return a stream. + </p> +@@ -587,7 +606,7 @@ stream-define are both library procedures, not fundamental to the use + of streams, and are thus excluded from this SRFI. + </p> + +-<H1>Specification</H1> ++<h2>Specification</h2> + + <p>A <i>stream-pair</i> is a data structure consisting of two fields called + the <i>stream-car</i> and <i>stream-cdr</i>. Stream-pairs are created +@@ -629,23 +648,25 @@ to detect and report errors. + </p> + + <dl> +-<dt> +-<code><a name="stream-null">stream-null</a></code> (constant)</dt> ++<dt id="stream-null"> ++<code>stream-null</code> (constant)</dt> + <dd> ++<p> + <code>Stream-null</code> is the distinguished nil stream, a single + Scheme object distinguishable from all other objects. If the last + stream-pair in a stream contains stream-null in its cdr field, the + stream is finite and has a computable length. However, there is no + need for streams to terminate. +- ++</p> + <pre> +- stream-null => (stream) ++ stream-null => (stream) + </pre> + </dd> + +-<dt> +-<code><a name="stream-cons">(stream-cons <i>object</i> <i>stream</i>)</a></code> (syntax)</dt> ++<dt id="stream-cons"> ++<code>(stream-cons <i>object</i> <i>stream</i>)</code> (syntax)</dt> + <dd> ++<p> + <code>Stream-cons</code> is the primitive constructor of streams, + returning a stream with the given object in its car field and the + given stream in its cdr field. The stream returned by +@@ -654,7 +675,7 @@ given stream in its cdr field. The stream returned by + of any type, and there is no requirement that successive elements of a + stream be of the same type, although it is common for them to be. It + is an error if the second argument of <code>stream-cons</code> is not a stream. +- ++</p> + <pre> (stream-cons 'a stream-null) => (stream 'a) + (stream-cons 'a (stream 'b 'c 'd)) => (stream 'a 'b 'c 'd) + (stream-cons "a" (stream 'b 'c)) => (stream "a" 'b 'c) +@@ -663,73 +684,78 @@ is an error if the second argument of <code>stream-cons</code> is not a stream. + </pre> + </dd> + +-<dt> +-<code><a name="streamp">(stream? <i>object</i>)</a></code> (function)</code></dt> ++<dt id="streamp"> ++<code>(stream? <i>object</i>)</code> (function)</dt> + <dd> ++<p> + <code>Stream?</code> returns <code>#t</code> if the object is a stream, and otherwise returns <code>#f</code>. A stream + object may be either the null stream or a stream pair created by <code>stream-cons</code>. +- ++</p> + <pre> (stream? stream-null) => #t + (stream? (stream-cons 'a stream-null)) => #t + (stream? 3) => #f + </pre> + </dd> + +-<dt> +-<code><a name="stream-nullp">(stream-null? <i>object</i>)</a></code> (function)</code></dt> ++<dt id="stream-nullp"> ++<code>(stream-null? <i>object</i>)</code> (function)</dt> + <dd> ++<p> + <code>Stream-null?</code> returns <code>#t</code> if the object is the distinguished nil stream, and +-otherwise returns <code>#f</code. +- ++otherwise returns <code>#f</code>. ++</p> + <pre> (stream-null? stream-null) => #t + (stream-null? (stream-cons 'a stream-null)) => #f + (stream-null? 3) => #f + </pre> + </dd> + +-<dt> +-<code><a name="stream-pairp">(stream-pair? <i>object</i>)</a></code> (function)</dt> ++<dt id="stream-pairp"> ++<code>(stream-pair? <i>object</i>)</code> (function)</dt> + <dd> ++<p> + <code>Stream-pair?</code> returns <code>#t</code> if the object is a stream pair created by stream-cons, and + otherwise returns <code>#f</code>. +- ++</p> + <pre> (stream-pair? stream-null) => #f + (stream-pair? (stream-cons 'a stream-null)) => #t + (stream-pair? 3) => #f + </pre> + </dd> + +-<dt> +-<code><a name="stream-car">(stream-car <i>stream</i>)</a></code> (function)</dt> ++<dt id="stream-car"> ++<code>(stream-car <i>stream</i>)</code> (function)</dt> + <dd> ++<p> + <code>Stream-car</code> returns the object in the stream-car field of + a stream-pair. It is an error to attempt to evaluate the stream-car + of stream-null. +- ++</p> + <pre> (stream-car (stream 'a 'b 'c)) => a + (stream-car stream-null) => error + (stream-car 3) => error + </pre> + </dd> + +-<dt> +-<code><a name="stream-cdr">(stream-cdr <i>stream</i>)</a></code> (function)</dt> ++<dt id="stream-cdr"> ++<code>(stream-cdr <i>stream</i>)</code> (function)</dt> + <dd> ++<p> + <code>Stream-cdr</code> returns the stream in the stream-cdr field of + a stream-pair. It is an error to attempt to evaluate the stream-cdr + of stream-null. +-</code> +- ++</p> + <pre> (stream-cdr (stream 'a 'b 'c)) => (stream 'b 'c) + (stream-cdr stream-null) => error + (stream-cdr 3) => error +-</code> ++ + </pre> + </dd> + +-<dt> +-<code><a name="stream-delay">(stream-delay <i>expression</i>)</a></code> (syntax)</dt> ++<dt id="stream-delay"> ++<code>(stream-delay <i>expression</i>)</code> (syntax)</dt> + <dd> ++<p> + <code>Stream-delay</code> is the essential mechanism for operating on streams, taking an + expression and returning a delayed form of the expression that can be asked at + some future point to evaluate the expression and return the resulting value. The +@@ -737,7 +763,7 @@ action of stream-delay is analogous to the action of delay, but it is specific t + the stream data type, returning a stream instead of a promise; no corresponding + <code>stream-force</code> is required, because each of the stream functions performs the force + implicitly. +- ++</p> + <pre> (define from0 + (let loop ((x 0)) + (stream-delay +@@ -746,26 +772,28 @@ implicitly. + </pre> + </dd> + +-<dt><code><a name="stream">(stream <i>object</i> ...)</a></code> (library function) ++<dt id="stream"><code>(stream <i>object</i> ...)</code> (library function)</dt> + <dd> ++<p> + <code>Stream</code> returns a newly allocated finite stream of its arguments, in order. +- ++</p> + <pre> (stream 'a (+ 3 4) 'c) => (stream 'a 7 'c) + (stream) => stream-null + </pre> + </dd> + + <dt> +-<code><a name="stream-unfoldn">(stream-unfoldn <i>generator</i> <i>seed</i> <i>n</i>)</a></code> ++<code id="stream-unfoldn">(stream-unfoldn <i>generator</i> <i>seed</i> <i>n</i>)</code> + (function)</dt> + <dd> ++<p> + <code>Stream-unfoldn</code> returns <i>n</i> streams whose contents are produced by successive calls + to generator, which takes the current seed as an arguments and returns <i>n</i> + 1 + values: +- ++</p> + <p> +-<code>(<i>proc</i> <i>seed</i>)</code> -> <i>seed</i> <i>result0</i> ... <i>resultN</i> +- ++<code>(<i>proc</i> <i>seed</i>)</code> -> <i>seed</i> <i>result0</i> ... <i>resultN</i> ++</p> + <p> + where <i>resultI</i> indicates how to produce the next element of the Ith result stream: + </p> +@@ -806,8 +834,8 @@ multiple calls to generator. + </pre> + </dd> + +-<dt> +-<code><a name="stream-map">(stream-map <i>function</i> <i>stream</i> ...)</a></code> (library ++<dt id="stream-map"> ++<code>(stream-map <i>function</i> <i>stream</i> ...)</code> (library + function)</dt> + <dd> + <code>Stream-map</code> creates a newly allocated stream built by +@@ -826,8 +854,8 @@ streams are infinite. The stream elements are evaluated in order. + </pre> + </dd> + +-<dt> +-<code><a name="stream-for-each">(stream-for-each <i>procedure</i> <i>stream</i> ...)</a></code> ++<dt id="stream-for-each"> ++<code>(stream-for-each <i>procedure</i> <i>stream</i> ...)</code> + (library function)</dt> + <dd> + <code>Stream-for-each</code> applies procedure elementwise to the elements of the streams, +@@ -839,8 +867,8 @@ stream-for-each is unspecified. The stream elements are visited in order. + </pre> + </dd> + +-<dt> +-<code><a name="stream-filter">(stream-filter <i>predicate?</i> <i>stream</i>)</a></code> (library function)</dt> ++<dt id="stream-filter"> ++<code>(stream-filter <i>predicate?</i> <i>stream</i>)</code> (library function)</dt> + <dd> + <code>Stream-filter</code> applies <i>predicate?</i> to each element + of stream and creates a newly allocated stream consisting of those +@@ -855,18 +883,16 @@ same order as they were in the input stream, and are tested by + </dd> + </dl> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + + <p> A reference implementation of streams is shown below. It strongly + prefers simplicity and clarity to efficiency, and though a reasonable + attempt is made to be safe-for-space, no promises are made. The reference +-implementation relies on the mechanism for defining record types of <a +-href="http://srfi.schemers.org/srfi-9/">SRFI-9</a>, and the functions +-<code>any</code> and <code>every</code> from <a +-href=""http://srfi.schemers.org/srfi-1/">SRFI-1</a>. The ++implementation relies on the mechanism for defining record types of <a href="srfi-9.html">SRFI-9</a>, and the functions ++<code>any</code> and <code>every</code> from <a href="srfi-1.html">SRFI-1</a>. The + <code>stream-error</code> function aborts by calling <code>error</code> as +-defined in <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a>. +- ++defined in <a href="srfi-23.html">SRFI 23</a>. ++</p> + <pre>;;; PROMISES A LA SRFI-45: + + ;;; A separate implementation is necessary to +@@ -1038,15 +1064,17 @@ defined in <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a>. + ((not (stream? strm)) (stream-error "attempt to apply stream-filter to non-stream")) + (else (stream-unfoldn + (lambda (s) +- (values +- (stream-cdr s) +- (cond ((stream-null? s) '()) +- ((pred? (stream-car s)) (list (stream-car s))) +- (else #f)))) ++ (cond ++ ((stream-null? s) ++ (values stream-null '())) ++ ((pred? (stream-car s)) ++ (values (stream-cdr s) (list (stream-car s)))) ++ (else ++ (values (stream-cdr s) #f)))) + strm + 1))))</pre> + +-<H1>References</H1> ++<h2>References</h2> + + <ul> + <li> +@@ -1078,8 +1106,8 @@ Workshop on ML, pp. 24-30. + <a name="lisp"></a> + Patrick H. Winston, Berthold K. Horn: <i>Lisp</i>, 3rd edition, + Addison Wesley, 1989. +-</ul> +-<H1>Copyright</H1> ++</li></ul> ++<h2>Copyright</h2> + <p>Copyright (C) 2003 by Philip L. Bewig of Saint Louis, Missouri, United States of + America. All rights reserved.</p> + +@@ -1106,11 +1134,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Mon Feb 3 14:53:23 MET 2003 --> + <!-- hhmts start --> +-Last modified: Sat Sep 11 12:40:31 MST 2004 ++Last modified: Fri Jan 25 11:19:45 CET 2008 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html +index a937761..6604d2f 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-41/srfi-41.html +@@ -1,42 +1,55 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html><head><title>SRFI 41: Streams</title></head><body> +- +-<h1>Title</h1> +- +-Streams +- +- +-<h1>Author</h1> +- +-Philip L. Bewig +- +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-To comment on this SRFI, please <code> +-<a href="mailto:srfi%20minus%2041%20at%20srfi%20dot%20schemers%20dot%20org">mailto:srfi minus 41 at srfi dot schemers dot org</a></code>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-41/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-41/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-41 ┃ ++┃ Commit: 0b47be664e80f0e55b345d0bd706385c8b89c407 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 41: Streams</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="../racket-srfi.css" /> ++ <script type="text/javascript" src="../../../doc-site.js"></script> ++ </head> ++ ++ <body> ++ ++<h1>SRFI 41: Streams</h1> ++ ++<p>by Philip L. Bewig</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 41 specification document ++is distributed as part of the Racket package ++<a href="../../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-41/srfi-41.html">https://srfi.schemers.org/srfi-41/srfi-41.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+41+at+srfi+dotschemers+dot+org">srfi-41@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-41">archive</a>.</p> + + <ul> +-<li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-41/srfi-41.html?rev=1.2">2007/10/24</a> +-</li><li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-41/srfi-41.html?rev=1.3">2007/11/14</a> +-</li><li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-41/srfi-41.html?rev=1.5">2007/11/14</a> +-</li><li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-41/srfi-41.html?rev=1.6">2007/12/17</a> +-</li><li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-41/srfi-41.html?rev=1.7">2008/01/24</a> +-</li><li>Draft: 2007/10/21 - 2007/12/22 ++<li>Received: <a href="https://srfi.schemers.org/srfi-41/srfi-41-1.2.html">2007-10-24</a> ++</li><li>Revised: <a href="https://srfi.schemers.org/srfi-41/srfi-41-1.3.html">2007-11-14</a> ++</li><li>Revised: <a href="https://srfi.schemers.org/srfi-41/srfi-41-1.5.html">2007-11-14</a> ++</li><li>Revised: <a href="https://srfi.schemers.org/srfi-41/srfi-41-1.6.html">2007-12-17</a> ++</li><li>Final: <a href="https://srfi.schemers.org/srfi-41/srfi-41-1.7.html">2008-01-24</a> ++</li><li>Post-finalization improvement to <code>stream-constant</code>: ++ <a href="https://srfi-email.schemers.org/srfi-41/dates/2015/10">2015-11-02</a></li> ++<li>Draft: 2007-10-21--2007-12-22 + </li></ul> +- +-<h1>Abstract</h1> ++ ++<h2>Abstract</h2> + + <p align="justify"><font face="serif">Streams, sometimes + called lazy lists, are a sequential data structure containing elements +@@ -60,16 +73,16 @@ stream libraries, say:</font></p> + + <p align="justify"><font face="monospace">(import (streams))</font></p> + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + + <p align="justify"><font face="serif">Harold Abelson + and Gerald Jay Sussman discuss streams at length, giving a strong justification + for their use. The streams they provide are represented as a </font><font face="monospace">cons</font><font face="serif"> + pair with a promise to return a stream in its </font><font face="monospace">cdr</font><font face="serif">; for instance, a stream with elements + the first three counting numbers is represented conceptually as </font><font face="monospace">(cons 1 (delay (cons 2 (delay (cons 3 (delay +-'()))))))</font><font face="serif">.</font><font face="monospace"> </font><font face="serif">Philip Wadler, Walid Taha and David +-MacQueen describe such streams as <i>odd</i> because, regardless of +-their length, the parity of the number of constructors (</font><font face="monospace">delay</font><font face="serif">, </font><font face="monospace">cons</font><font face="serif">, </font><font face="monospace">'()</font><font face="serif">) ++'()))))))</font><font face="serif">.</font><font face="monospace"> </font><font face="serif">Philip Wadler, Walid Taha and David ++MacQueen describe such streams as <i>odd</i> because, regardless of ++their length, the parity of the number of constructors (</font><font face="monospace">delay</font><font face="serif">, </font><font face="monospace">cons</font><font face="serif">, </font><font face="monospace">'()</font><font face="serif">) + in the stream is odd.</font></p> + + <p align="justify"><font face="serif">The streams +@@ -105,7 +118,7 @@ of items as a whole, similar to a pipeline of unix commands.</font></p> + + <p align="justify"><font face="serif">In addition + to improved modularity, streams permit a clear exposition of backtracking +-algorithms using the “stream of successes” technique, and they can ++algorithms using the “stream of successes” technique, and they can + be used to model generators and co-routines. The implicit memoization + of streams makes them useful for building persistent data structures, + and the laziness of streams permits some multi-pass algorithms to be +@@ -121,9 +134,9 @@ savings are needed, or when they offer a clearer exposition of the algorithms + that operate on the sequence.</font></p> + + +-<h1>Specification</h1> ++<h2>Specification</h2> + +-<h2>The <font face="monospace">(streams primitive)</font><font face="serif"> library</font></h2> ++<h3>The <font face="monospace">(streams primitive)</font><font face="serif"> library</font></h3> + + <font face="serif">The </font><font face="monospace">(streams primitive)</font><font face="serif"> + library provides two mutually-recursive abstract data types: An +@@ -132,12 +145,14 @@ when forced, is either </font><font face="monospace">stream-null</font><font fac + An object of the </font><font face="monospace">stream-pair</font><font face="serif"> abstract data type contains a </font><font face="monospace">stream-car</font><font face="serif"> + and a </font><font face="monospace">stream-cdr</font><font face="serif">, which must be a </font><font face="monospace">stream</font><font face="serif">. The essential feature of streams + is the systematic suspensions of the recursive promises between the +-two data types.</font><p></p> ++two data types.</font> + +-<p align="justify"><font face="monospace"><pre>α stream ++<p align="justify"><font face="monospace"><pre> ++α stream + :: (promise stream-null) +- | (promise (α stream-pair))</pre><pre>α stream-pair +- :: (promise α) × (promise (α stream))</pre></font></p> ++ | (promise (α stream-pair))</pre><pre> ++α stream-pair ++ :: (promise α) × (promise (α stream))</pre></font></p> + + <p align="justify"><font face="serif">The object + stored in the </font><font face="monospace">stream-car</font><font face="serif"> of a </font><font face="monospace">stream-pair</font><font face="serif"> is a promise that is forced the first +@@ -152,12 +167,12 @@ provides eight operators: constructors for </font><font face="monospace">stream- + the two kinds of streams, accessors for both fields of a </font><font face="monospace">stream-pair</font><font face="serif">, + and a lambda that creates procedures that return streams.</font></p> + +-<p align="justify"><font face="serif"><b>constructor: </b></font><font face="monospace"><b>stream-null</b></font><br> ++<p align="justify" id="stream-null"><font face="serif"><b>constructor: </b></font><font face="monospace"><b>stream-null</b></font><br /> + <font face="monospace">Stream-null</font><font face="serif"> is a promise that, when forced, is + a single object, distinguishable from all other objects, that represents + the null stream. </font><font face="monospace">Stream-null</font><font face="serif"> is immutable and unique.</font></p> + +-<p align="justify"><font face="monospace"><font face="serif"><b>constructor: </b></font><b>(stream-cons </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream-cons"><font face="monospace"><font face="serif"><b>constructor: </b></font><b>(stream-cons </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-cons</font><font face="serif"> is a macro that accepts an <i>object</i> + and a <i>stream</i> and creates a newly-allocated </font><font face="monospace">stream</font><font face="serif"> containing a promise that, when forced, + is a </font><font face="monospace">stream-pair</font><font face="serif"> with the <i>object</i> in its </font><font face="monospace">stream-car</font><font face="serif"> +@@ -170,7 +185,7 @@ however, doing so will cause an error later when the </font><font face="monospac + is immutable; there is no </font><font face="monospace">stream-set-car!</font><font face="serif"> or </font><font face="monospace">stream-set-cdr!</font><font face="serif"> that modifies an existing </font><font face="monospace">stream-pair</font><font face="serif">. + There is no dotted-pair or improper stream as with lists.</font></p> + +-<p align="justify"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream?"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream?</font><font face="serif"> is a procedure that takes an <i>object</i> + and returns </font><font face="monospace">#t</font><font face="serif"> + if the <i>object</i> is a stream and </font><font face="monospace">#f</font><font face="serif"> otherwise. If <i>object</i> +@@ -183,35 +198,35 @@ obj)</font><font face="serif"> is </font><font face="monospace">#f</font><font f + obj)</font><font face="serif"> and </font><font face="monospace">(stream-pair? + obj)</font><font face="serif"> will be </font><font face="monospace">#f</font><font face="serif">. </font></p> + +-<p align="justify"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream-null? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream-null?"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream-null? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-null?</font><font face="serif"> is a procedure that takes an <i>object</i> + and returns </font><font face="monospace">#t</font><font face="serif"> + if the <i>object</i> is the distinguished null stream and </font><font face="monospace">#f</font><font face="serif"> + otherwise. If <i>object</i> is a stream, </font><font face="monospace">stream-null?</font><font face="serif"> must force its promise in order to + distinguish </font><font face="monospace">stream-null</font><font face="serif"> from </font><font face="monospace">stream-pair</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream-pair? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream-pair?"><font face="serif"><b>recognizer: </b></font><font face="monospace"><b>(stream-pair? </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-pair?</font><font face="serif"> is a procedure that takes an <i>object</i> + and returns </font><font face="monospace">#t</font><font face="serif"> + if the <i>object</i> is a </font><font face="monospace">stream-pair</font><font face="serif"> constructed by </font><font face="monospace">stream-cons</font><font face="serif"> and </font><font face="monospace">#f</font><font face="serif"> otherwise. If <i>object</i> + is a stream, </font><font face="monospace">stream-pair?</font><font face="serif"> must force its promise in order to + distinguish </font><font face="monospace">stream-null</font><font face="serif"> from </font><font face="monospace">stream-pair</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><b>accessor: </b></font><font face="monospace"><b>(stream-car </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream-car"><font face="serif"><b>accessor: </b></font><font face="monospace"><b>(stream-car </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-car</font><font face="serif"> is a procedure that takes a <i>stream</i> + and returns the object stored in the </font><font face="monospace">stream-car</font><font face="serif"> of the <i>stream</i>. </font><font face="monospace">Stream-car</font><font face="serif"> + signals an error if the object passed to it is not a </font><font face="monospace">stream-pair</font><font face="serif">. Calling </font><font face="monospace">stream-car</font><font face="serif"> causes the object stored there to +-be evaluated if it has not yet been; the object’s value is cached ++be evaluated if it has not yet been; the object’s value is cached + in case it is needed again.</font></p> + +-<p align="justify"><font face="serif"><b>accessor: </b></font><font face="monospace"><b>(stream-cdr </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> ++<p align="justify" id="stream-cdr"><font face="serif"><b>accessor: </b></font><font face="monospace"><b>(stream-cdr </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-cdr</font><font face="serif"> is a procedure that takes a <i>stream</i> + and returns the stream stored in the </font><font face="monospace">stream-cdr</font><font face="serif"> of the <i>stream</i>. </font><font face="monospace">Stream-cdr</font><font face="serif"> + signals an error if the object passed to it is not a </font><font face="monospace">stream-pair</font><font face="serif">. Calling </font><font face="monospace">stream-cdr</font><font face="serif"> + does not force the promise containing the stream stored in the +-</font><font face="monospace">stream-cdr</font><font face="serif"> of the <i>stream</i>. ++</font><font face="monospace">stream-cdr</font><font face="serif"> of the <i>stream</i>.</font></p> + +-</font></p><p align="justify"><font face="serif"><font face="serif"><b>lambda: </b></font><font face="serif"><b>(</b></font><font face="monospace"><b>stream-lambda </b></font><font face="serif"><b><i>args</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>body</i>)</b></font><br> ++<p align="justify" id="stream-lambda"><font face="serif"><b>lambda: </b></font><font face="serif"><b>(</b></font><font face="monospace"><b>stream-lambda </b></font><font face="serif"><b><i>args</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>body</i>)</b></font><br /> + <font face="monospace">Stream-lambda</font><font face="serif"> creates a procedure that returns a + promise to evaluate the <i>body</i> of the procedure. The last <i> + body</i> expression to be evaluated must yield a stream. As with +@@ -222,178 +237,188 @@ which may be null if there are no arguments, proper if there are an + exact number of arguments, or dotted if a fixed number of arguments + is to be followed by zero or more arguments collected into a list. <i> + Body</i> must contain at least one expression, and may contain internal +-definitions preceding any expressions to be evaluated.</font></font></p> ++definitions preceding any expressions to be evaluated.</font></p> + +-<p align="justify"><font face="serif"><font face="monospace"></font></font></p><pre><font face="serif"><font face="monospace">(define strm123 ++<p align="justify"><font face="monospace"><pre> ++(define strm123 + (stream-cons 1 + (stream-cons 2 + (stream-cons 3 +- stream-null))))</font></font></pre><p></p> ++ stream-null))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car strm123) </font><font face="Symbol">⇒</font><font face="monospace"> +-1</font></font></p> ++<p align="justify"><font face="monospace">(stream-car strm123) </font><font face="Symbol">⇒</font><font face="monospace"> ++1</font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car (stream-cdr +-strm123) </font><font face="Symbol">⇒</font><font face="monospace"> +-2</font></font></p> ++<p align="justify"><font face="monospace">(stream-car (stream-cdr ++strm123) </font><font face="Symbol">⇒</font><font face="monospace"> ++2</font></p> + +-<p align="justify"><font face="serif"><font face="monospace"></font></font></p><pre><font face="serif"><font face="monospace">(stream-pair? ++<p align="justify"><font face="monospace"><pre> ++(stream-pair? + (stream-cdr +- (stream-cons (/ 1 0) stream-null))) </font><font face="Symbol">⇒</font><font face="monospace"> #f</font></font></pre><p></p> ++ (stream-cons (/ 1 0) stream-null))) ⇒ #f</pre></font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream? (list +-1 2 3)) </font><font face="Symbol">⇒</font><font face="monospace"> +-#f</font></font></p> ++<p align="justify"><font face="monospace">(stream? (list ++1 2 3)) </font><font face="Symbol">⇒</font><font face="monospace"> ++#f</font></p> + +-<p align="justify"><font face="serif"><font face="monospace"></font></font></p><pre><font face="serif"><font face="monospace">(define iter ++<p align="justify"><font face="monospace"><pre> ++(define iter + (stream-lambda (f x) +- (stream-cons x (iter f (f x)))))</font></font></pre><p></p> ++ (stream-cons x (iter f (f x)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(define nats (iter +-(lambda (x) (+ x 1)) 0))</font></font></p> ++<p align="justify"><font face="monospace">(define nats (iter ++(lambda (x) (+ x 1)) 0))</font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car (stream-cdr +-nats)) </font><font face="Symbol">⇒</font><font face="monospace"> +-1</font></font></p> ++<p align="justify"><font face="monospace">(stream-car (stream-cdr ++nats)) </font><font face="Symbol">⇒</font><font face="monospace"> ++1</font></p> + +-<p align="justify"><font face="serif"><font face="monospace"></font></font></p><pre><font face="serif"><font face="monospace">(define stream-add ++<p align="justify"><font face="monospace"><pre> ++(define stream-add + (stream-lambda (s1 s2) + (stream-cons + (+ (stream-car s1) (stream-car s2)) + (stream-add (stream-cdr s1) +- (stream-cdr s2)))))</font></font></pre><p></p> ++ (stream-cdr s2)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(define evens (stream-add +-nats nats))</font></font></p> ++<p align="justify"><font face="monospace">(define evens (stream-add ++nats nats))</font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car evens) </font><font face="Symbol">⇒</font><font face="monospace"> 0</font></font></p> ++<p align="justify"><font face="monospace">(stream-car evens) </font><font face="Symbol">⇒</font><font face="monospace"> 0</font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car (stream-cdr +-evens)) </font><font face="Symbol">⇒</font><font face="monospace"> +-2</font></font></p> ++<p align="justify"><font face="monospace">(stream-car (stream-cdr ++evens)) </font><font face="Symbol">⇒</font><font face="monospace"> ++2</font></p> + +-<p align="justify"><font face="serif"><font face="monospace">(stream-car (stream-cdr +-(stream-cdr evens))) </font><font face="Symbol">⇒</font><font face="monospace"> 4</font></font></p> ++<p align="justify"><font face="monospace">(stream-car (stream-cdr ++(stream-cdr evens))) </font><font face="Symbol">⇒</font><font face="monospace"> 4</font></p> + +-<h2><font face="serif">The <font face="monospace">(streams derived)</font><font face="serif"> library</font></font></h2> ++<h3>The <font face="monospace">(streams derived)</font><font face="serif"> library</font></h3> + +-<p align="justify"><font face="serif"><font face="serif">The </font><font face="monospace">(streams derived)</font><font face="serif"> ++<p align="justify"><font face="serif">The </font><font face="monospace">(streams derived)</font><font face="serif"> + library provides useful procedures and syntax that depend on the primitives + defined above. In the operator + templates given below, an ellipsis </font><font face="monospace">...</font><font face="serif"> indicates zero or more repetitions +-of the preceding subexpression and square brackets </font><font face="monospace">[…]</font><font face="serif"> indicate optional elements. +-In the type annotations given below, square brackets </font><font face="monospace">[…]</font><font face="serif"> refer to lists, curly braces </font><font face="monospace">{…}</font><font face="serif"> +-refer to streams, and </font><font face="monospace">nat</font><font face="serif"> refers to exact non-negative integers.</font></font></p> ++of the preceding subexpression and square brackets </font><font face="monospace">[…]</font><font face="serif"> indicate optional elements. ++In the type annotations given below, square brackets </font><font face="monospace">[…]</font><font face="serif"> refer to lists, curly braces </font><font face="monospace">{…}</font><font face="serif"> ++refer to streams, and </font><font face="monospace">nat</font><font face="serif"> refers to exact non-negative integers.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><b>syntax: </b></font><font face="monospace"><b>(define-stream +-(</b></font><font face="serif"><b><i>name</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>args</i></b></font><font face="monospace"><b>) </b></font><font face="serif"><b><i>body</i></b></font><font face="monospace"><b>) </b></font><br> ++<p align="justify" id="define-stream"><font face="serif"><b>syntax: </b></font><font face="monospace"><b>(define-stream ++(</b></font><font face="serif"><b><i>name</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>args</i></b></font><font face="monospace"><b>) </b></font><font face="serif"><b><i>body</i></b></font><font face="monospace"><b>) </b></font><br /> + <font face="monospace">Define-stream</font><font face="serif"> creates a procedure that returns a + stream, and may appear anywhere a normal </font><font face="monospace">define</font><font face="serif"> may appear, including as an internal + definition, and may have internal definitions of its own, including + other </font><font face="monospace">define-stream</font><font face="serif">s. The defined procedure takes + arguments in the same way as </font><font face="monospace">stream-lambda</font><font face="serif">. </font><font face="monospace">Define-stream</font><font face="serif"> is syntactic sugar on </font><font face="monospace">stream-lambda</font><font face="serif">; +-see also </font><font face="monospace">stream-let</font><font face="serif">, which is also a sugaring of </font><font face="monospace">stream-lambda</font><font face="serif">.</font></font></p> ++see also </font><font face="monospace">stream-let</font><font face="serif">, which is also a sugaring of </font><font face="monospace">stream-lambda</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif">A simple version of <font face="monospace">stream-map</font> +-<font face="serif"> that takes only a single input stream calls itself recursively:</font></font></font></p> ++<p align="justify"><font face="serif">A simple version of </font><font face="monospace">stream-map</font> ++<font face="serif"> that takes only a single input stream calls itself recursively:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-map proc strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-map proc strm) + (if (stream-null? strm) + stream-null + (stream-cons + (proc (stream-car strm)) +- (stream-map proc (stream-cdr strm))))))</pre></font></font></font></p> ++ (stream-map proc (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(list->stream </b></font><font face="serif"><b><i>list-of-objects</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">[α] → {α}</font><br> ++<p align="justify" id="list-to-stream"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(list->stream </b></font><font face="serif"><b><i>list-of-objects</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">[α] → {α}</font><br /> + <font face="monospace">List->stream</font><font face="serif"> takes a list of objects and returns + a newly-allocated stream containing in its elements the objects in the + list. Since the objects are given in a list, they are evaluated + when </font><font face="monospace">list->stream</font><font face="serif"> is called, before the stream is created. + If the list of objects is null, as in </font><font face="monospace">(list->stream +-'())</font><font face="serif">, the null stream is +-returned. See also </font><font face="monospace">stream</font><font face="serif">.</font></font></font></p> ++'())</font><font face="serif">, the null stream is ++returned. See also </font><font face="monospace">stream</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define strm123 (list->stream '(1 2 3)))</font></font></font></p> ++<p align="justify"><font face="monospace">(define strm123 (list->stream '(1 2 3)))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"> ++<p align="justify"><font face="monospace"> + <pre>; fails with divide-by-zero error +-(define s (list->stream (list 1 (/ 1 0) -1)))</pre></font></font></font></p> ++(define s (list->stream (list 1 (/ 1 0) -1)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(port->stream +-[</b></font><font face="serif"><b><i>port</i></b></font><font face="monospace"><b>])</b></font><br> +-<font face="monospace">port → {char}</font><br> ++<p align="justify" id="port-to-stream"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(port->stream ++[</b></font><font face="serif"><b><i>port</i></b></font><font face="monospace"><b>])</b></font><br /> ++<font face="monospace">port → {char}</font><br /> + <font face="monospace">Port->stream</font><font face="serif"> takes a <i>port</i> and returns a + newly-allocated stream containing in its elements the characters on + the port. If <i>port</i> is not given it defaults to the current + input port. The returned stream has finite length and is terminated +-by </font><font face="monospace">stream-null</font><font face="serif">.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It looks like +-one use of </font><font face="monospace">port->stream</font><font face="serif"> would be this:</font></font></font></p> ++by </font><font face="monospace">stream-null</font><font face="serif">.</font></p> ++<p align="justify"><font face="serif">It looks like ++one use of </font><font face="monospace">port->stream</font><font face="serif"> would be this:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define s ;wrong! ++<p align="justify"><font face="monospace"><pre> ++(define s ;wrong! + (with-input-from-file filename +- (lambda () (port->stream))))</pre></font></font></font></p> ++ (lambda () (port->stream))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">But that fails, ++<p align="justify"><font face="serif">But that fails, + because </font><font face="monospace">with-input-from-file</font><font face="serif"> is eager, and closes the input port + prematurely, before the first character is read. To read a file +-into a stream, say:</font></font></font></p> ++into a stream, say:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (file->stream filename) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (file->stream filename) + (let ((p (open-input-file filename))) + (stream-let loop ((c (read-char p))) + (if (eof-object? c) + (begin (close-input-port p) + stream-null) + (stream-cons c +- (loop (read-char p)))))))</pre></font></font></font></p> ++ (loop (read-char p)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>syntax: </b></font><font face="monospace"><b>(stream </b></font><font face="serif"><b><i>object</i> </b></font><font face="monospace"><b>...)</b></font><br> ++<p align="justify" id="stream"><font face="serif"><b>syntax: </b></font><font face="monospace"><b>(stream </b></font><font face="serif"><b><i>object</i> </b></font><font face="monospace"><b>...)</b></font><br /> + <font face="monospace">Stream</font><font face="serif"> is syntax that takes zero or more <i> + object</i>s and creates a newly-allocated stream containing in its elements + the <i>object</i>s, in order. Since </font><font face="monospace">stream</font><font face="serif"> is syntactic, the <i>object</i>s are + evaluated when they are accessed, not when the stream is created. + If no <i>object</i>s are given, as in </font><font face="monospace">(stream)</font><font face="serif">, the null stream is returned. +-See also </font><font face="monospace">list->stream</font><font face="serif">.</font></font></font></p> ++See also </font><font face="monospace">list->stream</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define strm123 (stream 1 2 3))</font></font></font></p> ++<p align="justify"><font face="monospace">(define strm123 (stream 1 2 3))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>; (/ 1 0) not evaluated when stream is created +-(define s (stream 1 (/ 1 0) -1))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++; (/ 1 0) not evaluated when stream is created ++(define s (stream 1 (/ 1 0) -1))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream->list +-[</b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b>] </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">nat × {α} → [α]</font><br> ++<p align="justify" id="stream-to-list"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream->list ++[</b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b>] </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">nat × {α} → [α]</font><br /> + <font face="monospace">Stream->list</font><font face="serif"> takes a natural number <i>n</i> and + a <i>stream</i> and returns a newly-allocated list containing in its + elements the first <i>n</i> items in the <i>stream</i>. If the <i>stream</i> + has less than <i>n</i> items all the items in the <i>stream</i> will + be included in the returned list. If <i>n</i> is not given it + defaults to infinity, which means that unless <i>stream</i> is finite </font><font face="monospace">stream->list</font><font face="serif"> +-will never return.</font></font></font></p> ++will never return.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(stream->list 10 ++<p align="justify"><font face="monospace"><pre> ++(stream->list 10 + (stream-map (lambda (x) (* x x)) + (stream-from 0))) +- </font><font face="Symbol">⇒</font><font face="monospace"> (0 1 4 9 16 25 36 49 64 81)</font></font></font></pre><p></p> ++ ⇒ (0 1 4 9 16 25 36 49 64 81)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b> +-</font><font face="monospace"><b>(stream-append </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br> +-<font face="monospace">{α} ... → {α}</font><br> ++<p align="justify" id="stream-append"><font face="serif"><b>procedure: </b> ++</font><font face="monospace"><b>(stream-append </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br /> ++<font face="monospace">{α} ... → {α}</font><br /> + <font face="monospace">Stream-append</font><font face="serif"> returns a newly-allocated stream containing + in its elements those elements contained in its input <i>stream</i>s, + in order of input. If any of the input <i>stream</i>s is infinite, + no elements of any of the succeeding input <i>stream</i>s will appear + in the output stream; thus, if </font><font face="monospace">x</font><font face="serif"> is infinite, </font><font face="monospace">(stream-append +-x y) ≡ x</font><font face="serif">. See also </font><font face="monospace">stream-concat</font><font face="serif">.</font></font></font></p> ++x y) ≡ x</font><font face="serif">. See also </font><font face="monospace">stream-concat</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Quicksort can ++<p align="justify"><font face="serif">Quicksort can + be used to sort a stream, using </font><font face="monospace">stream-append</font><font face="serif"> to build the output; the sort is lazy; + so if only the beginning of the output stream is needed, the end of +-the stream is never sorted.</font></font></font></p> ++the stream is never sorted.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (qsort lt? strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (qsort lt? strm) + (if (stream-null? strm) + stream-null + (let ((x (stream-car strm)) +@@ -407,9 +432,9 @@ the stream is never sorted.</font></font></font></p> + (qsort lt? + (stream-filter + (lambda (u) (not (lt? u x))) +- xs))))))</pre></font></font></font></p> ++ xs))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Note also that, ++<p align="justify"><font face="serif">Note also that, + when used in tail position as in </font><font face="monospace">qsort</font><font face="serif">, </font><font face="monospace">stream-append</font><font face="serif"> does not suffer the poor performance + of </font><font face="monospace">append</font><font face="serif"> + on lists. The list version of </font><font face="monospace">append</font><font face="serif"> requires re-traversal of all its list +@@ -419,29 +444,31 @@ the preceding elements of the result have already been traversed, so + tail-recursive loops that produce streams are efficient even when each + element is appended to the end of the result stream. This also + implies that during traversal of the result only one promise needs to +-be kept in memory at a time.</font></font></font></p> ++be kept in memory at a time.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-concat </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">{{α}} ... → {α}</font><br> ++<p align="justify" id="stream-concat"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-concat </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">{{α}} ... → {α}</font><br /> + <font face="monospace">Stream-concat</font><font face="serif"> takes a <i>stream</i> consisting of + one or more streams and returns a newly-allocated stream containing + all the elements of the input streams. If any of the streams in + the input <i>stream</i> is infinite, any remaining streams in the input <i> +-stream</i> will never appear in the output stream. See also </font><font face="monospace">stream-append</font><font face="serif">.</font></font></font></p> ++stream</i> will never appear in the output stream. See also </font><font face="monospace">stream-append</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream->list ++<p align="justify"><font face="monospace"><pre> ++(stream->list + (stream-concat + (stream + (stream 1 2) (stream) (stream 3 2 1)))) +- ⇒ (1 2 3 2 1)</pre></font></font></font></p> ++ ⇒ (1 2 3 2 1)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The permutations ++<p align="justify"><font face="serif">The permutations + of a finite stream can be determined by interleaving each element of + the stream in all possible positions within each permutation of the + other elements of the stream. </font><font face="monospace">Interleave</font><font face="serif"> returns a stream of streams with <i> +-x</i> inserted in each possible position of <i>yy</i>:</font></font></font></p> ++x</i> inserted in each possible position of <i>yy</i>:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (interleave x yy) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (interleave x yy) + (stream-match yy + (() (stream (stream x))) + ((y . ys) +@@ -449,55 +476,58 @@ x</i> inserted in each possible position of <i>yy</i>:</font></font></font></p> + (stream (stream-cons x yy)) + (stream-map + (lambda (z) (stream-cons y z)) +- (interleave x ys))))))</pre></font></font></font></p> ++ (interleave x ys))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (perms xs) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (perms xs) + (if (stream-null? xs) + (stream (stream)) + (stream-concat + (stream-map + (lambda (ys) + (interleave (stream-car xs) ys)) +- (perms (stream-cdr xs))))))</pre></font></font></font></p> ++ (perms (stream-cdr xs))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-constant </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b> ...)</b></font><br> +-<font face="monospace">α ... → {α}</font><br> ++<p align="justify" id="stream-constant"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-constant </b></font><font face="serif"><b><i>object</i></b></font><font face="monospace"><b> ...)</b></font><br /> ++<font face="monospace">α ... → {α}</font><br /> + <font face="monospace">Stream-constant</font><font face="serif"> takes one or more <i>object</i>s and + returns a newly-allocated stream containing in its elements the <i>object</i>s, +-repeating the <i>object</i>s in succession forever.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-constant +-1) </font><font face="Symbol">⇒</font><font face="monospace"> +-1 1 1 ...</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-constant +-#t #f) </font><font face="Symbol">⇒</font><font face="monospace"> +-#t #f #t #f #t #f ...</font></font></font></p> +- +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-drop </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><font face="serif"><b> procedure </b></font><br> +-<font face="monospace">nat × {α} → {α}</font><br> ++repeating the <i>object</i>s in succession forever.</font></p> ++<p align="justify"><font face="monospace">(stream-constant ++1) </font><font face="Symbol">⇒</font><font face="monospace"> ++1 1 1 ...</font></p> ++<p align="justify"><font face="monospace">(stream-constant ++#t #f) </font><font face="Symbol">⇒</font><font face="monospace"> ++#t #f #t #f #t #f ...</font></p> ++ ++<p align="justify" id="stream-drop"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-drop </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><font face="serif"><b> procedure </b></font><br /> ++<font face="monospace">nat × {α} → {α}</font><br /> + <font face="monospace">Stream-drop</font><font face="serif"> returns the suffix of the input <i> + stream</i> that starts at the next element after the first <i>n</i> + elements. The output stream shares structure with the input <i> + stream</i>; thus, promises forced in one instance of the stream are + also forced in the other instance of the stream. If the input <i> + stream</i> has less than <i>n</i> elements, </font><font face="monospace">stream-drop</font><font face="serif"> returns the null stream. See +-also </font><font face="monospace">stream-take</font><font face="serif">.</font></font></font></p> ++also </font><font face="monospace">stream-take</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-split n strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-split n strm) + (values (stream-take n strm) +- (stream-drop n strm)))</pre></font></font></font></p> ++ (stream-drop n strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-drop-while </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α → boolean) × {α} → {α}</font><br> ++<p align="justify" id="stream-drop-while"><font face="serif"><b>procedure: </b></font><font face="monospace"><b>(stream-drop-while </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α → boolean) × {α} → {α}</font><br /> + <font face="monospace">Stream-drop-while</font><font face="serif"> returns the suffix of the input <i> + stream</i> that starts at the first element <i>x</i> for which </font><font face="monospace">(pred? </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif"> + is </font><font face="monospace">#f</font><font face="serif">. + The output stream shares structure with the input <i>stream</i>. +-See also </font><font face="monospace">stream-take-while</font><font face="serif">.</font></font></font></p> ++See also </font><font face="monospace">stream-take-while</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-unique</font><font face="serif"> creates a new stream that retains +-only the first of any sub-sequences of repeated elements.</font></font></font></p> ++<p align="justify"><font face="monospace">Stream-unique</font><font face="serif"> creates a new stream that retains ++only the first of any sub-sequences of repeated elements.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-unique eql? strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-unique eql? strm) + (if (stream-null? strm) + stream-null + (stream-cons (stream-car strm) +@@ -505,22 +535,23 @@ only the first of any sub-sequences of repeated elements.</font></font></font></ + (stream-drop-while + (lambda (x) + (eql? (stream-car strm) x)) +- strm)))))</pre></font></font></font></p> ++ strm)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-filter </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α → boolean) × {α} → {α}</font><br> ++<p align="justify" id="stream-filter"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-filter </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α → boolean) × {α} → {α}</font><br /> + <font face="monospace">Stream-filter</font><font face="serif"> returns a newly-allocated stream that + contains only those elements <i>x</i> of the input <i>stream</i> for + which </font><font face="monospace">(</font><font face="serif"><i>pred?</i></font><font face="monospace"> </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif"> +-is non-</font><font face="monospace">#f</font><font face="serif">.</font></font></font></p> ++is non-</font><font face="monospace">#f</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-filter odd? (stream-from 0)) +- ⇒ 1 3 5 7 9 ...</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-filter odd? (stream-from 0)) ++ ⇒ 1 3 5 7 9 ...</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-fold </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α × β → α) × α × {β} → α</font><br> ++<p align="justify" id="stream-fold"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-fold </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α × β → α) × α × {β} → α</font><br /> + <font face="monospace">Stream-fold</font><font face="serif"> applies a binary <i>proc</i>edure + to <i>base</i> and the first element of <i>stream</i> to compute a new <i> + base</i>, then applies the <i>proc</i>edure to the new <i>base</i> and +@@ -533,34 +564,38 @@ See also </font><font face="monospace">stream-scan</font><font face="serif">, wh + For readers familiar with other functional languages, this is a left-fold; + there is no corresponding right-fold, since right-fold relies on finite + streams that are fully-evaluated, at which time they may as well be +-converted to a list.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-fold</font><font face="serif"> is often used to summarize a stream +-in a single value, for instance, to compute the maximum element of a stream.</font></font></font></p> ++converted to a list.</font></p> ++<p align="justify"><font face="monospace">Stream-fold</font><font face="serif"> is often used to summarize a stream ++in a single value, for instance, to compute the maximum element of a stream.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-maximum lt? strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-maximum lt? strm) + (stream-fold + (lambda (x y) (if (lt? x y) y x)) + (stream-car strm) +- (stream-cdr strm)))</pre></font></font></font></p> ++ (stream-cdr strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Sometimes, +-it is useful to have </font><font face="monospace">stream-fold</font><font face="serif"> defined only on non-null streams:</font></font></font></p> ++<p align="justify"><font face="serif">Sometimes, ++it is useful to have </font><font face="monospace">stream-fold</font><font face="serif"> defined only on non-null streams:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-fold-one proc strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-fold-one proc strm) + (stream-fold proc + (stream-car strm) +- (stream-cdr strm)))</pre></font></font></font></p> ++ (stream-cdr strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-minimum</font><font face="serif"> can then be defined as:</font></font></font></p> ++<p align="justify"><font face="monospace">Stream-minimum</font><font face="serif"> can then be defined as:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-minimum lt? strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-minimum lt? strm) + (stream-fold-one + (lambda (x y) (if (lt? x y) x y)) +- strm))</pre></font></font></font></p> ++ strm))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-fold</font><font face="serif"> can also be used to build a stream:</font></font></font></p> ++<p align="justify"><font face="monospace">Stream-fold</font><font face="serif"> can also be used to build a stream:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (isort lt? strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (isort lt? strm) + (define-stream (insert strm x) + (stream-match strm + (() (stream x)) +@@ -568,91 +603,95 @@ it is useful to have </font><font face="monospace">stream-fold</font><font face= + (if (lt? y x) + (stream-cons y (insert ys x)) + (stream-cons x strm))))) +- (stream-fold insert stream-null strm))</pre></font></font></font></p> ++ (stream-fold insert stream-null strm))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-for-each </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br> +-<font face="monospace">(α × β × ...) × {α} × {β} ...</font><br> ++<p align="justify" id="stream-for-each"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-for-each </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br /> ++<font face="monospace">(α × β × ...) × {α} × {β} ...</font><br /> + <font face="monospace">Stream-for-each</font><font face="serif"> applies a <i>proc</i>edure element-wise + to corresponding elements of the input <i>stream</i>s for its side-effects; + it returns nothing. </font><font face="monospace">Stream-for-each</font><font face="serif"> stops as soon as any of its input <i> +-stream</i>s is exhausted.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The following +-procedure displays the contents of a file:</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (display-file filename) ++stream</i>s is exhausted.</font></p> ++<p align="justify"><font face="serif">The following ++procedure displays the contents of a file:</font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (display-file filename) + (stream-for-each display +- (file->stream filename)))</pre></font></font></font></p> ++ (file->stream filename)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"> ++<p align="justify" id="stream-from"><font face="monospace"> + <font face="serif"><b>procedure: </b></font> + <b>(stream-from </b></font><font face="serif"><b><i>first</i></b></font><font face="monospace"><b> +-[</b></font><font face="serif"><b><i>step</i></b></font><font face="monospace"><b>])</b></font><br> +-<font face="monospace">number × number → {number}</font><br> ++[</b></font><font face="serif"><b><i>step</i></b></font><font face="monospace"><b>])</b></font><br /> ++<font face="monospace">number × number → {number}</font><br /> + <font face="monospace">Stream-from</font><font face="serif"> creates a newly-allocated stream that + contains <i>first</i> as its first element and increments each succeeding + element by <i>step</i>. If <i>step</i> is not given it defaults + to </font><font face="monospace">1</font><font face="serif">. <i> + First</i> and <i>step</i> may be of any numeric type. </font><font face="monospace">Stream-from</font><font face="serif"> + is frequently useful as a generator in </font><font face="monospace">stream-of</font><font face="serif"> expressions. See also </font><font face="monospace">stream-range</font><font face="serif"> +-for a similar procedure that creates finite streams.</font><font face="monospace"> </font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-from</font><font face="serif"> could be implemented as </font><font face="monospace">(stream-iterate (lambda (x) (+ x </font><font face="serif"><i>step</i></font><font face="monospace">)) </font><font face="serif"><i>first</i></font><font face="monospace">)</font><font face="serif">.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define nats (stream-from +-0)) </font><font face="Symbol">⇒</font><font face="monospace"> +-0 1 2 ...</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define odds (stream-from +-1 2)) </font><font face="Symbol">⇒</font><font face="monospace"> +-1 3 5 ...</font></font></font></p> +- +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-iterate proc base)</b></font><br> +-<font face="monospace">(α → α) × α → {α}</font><br> ++for a similar procedure that creates finite streams.</font><font face="monospace"> </font></p> ++<p align="justify"><font face="monospace">Stream-from</font><font face="serif"> could be implemented as </font><font face="monospace">(stream-iterate (lambda (x) (+ x </font><font face="serif"><i>step</i></font><font face="monospace">)) </font><font face="serif"><i>first</i></font><font face="monospace">)</font><font face="serif">.</font></p> ++<p align="justify"><font face="monospace">(define nats (stream-from ++0)) </font><font face="Symbol">⇒</font><font face="monospace"> ++0 1 2 ...</font></p> ++<p align="justify"><font face="monospace">(define odds (stream-from ++1 2)) </font><font face="Symbol">⇒</font><font face="monospace"> ++1 3 5 ...</font></p> ++ ++<p align="justify" id="stream-iterate"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-iterate proc base)</b></font><br /> ++<font face="monospace">(α → α) × α → {α}</font><br /> + <font face="monospace">Stream-iterate</font><font face="serif"> creates a newly-allocated stream containing <i> + base</i> in its first element and applies <i>proc</i> to each element + in turn to determine the succeeding element. See also </font><font face="monospace">stream-unfold</font><font face="serif"> +-and </font><font face="monospace">stream-unfolds</font><font face="serif">.</font></font></font></p> ++and </font><font face="monospace">stream-unfolds</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-iterate (lambda (x) (+ x 1)) 0) +- ⇒ 0 1 2 3 4 ...</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-iterate (lambda (x) (+ x 1)) 0) ++ ⇒ 0 1 2 3 4 ...</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(stream-iterate (lambda (x) (* x 2)) 1) +- ⇒ 1 2 4 8 16 ...</font></font></font></pre><p></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-iterate (lambda (x) (* x 2)) 1) ++ ⇒ 1 2 4 8 16 ...</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Given a <i> ++<p align="justify"><font face="serif">Given a <i> + seed</i> between </font><font face="monospace">0</font><font face="serif"> and </font><font face="monospace">2<sup>32</sup></font><font face="serif">, exclusive, the following expression + creates a stream of pseudo-random integers between </font><font face="monospace">0</font><font face="serif"> and </font><font face="monospace">2<sup>32</sup></font><font face="serif">, exclusive, beginning with <i>seed</i>, +-using the method described by Stephen Park and Keith Miller:</font></font></font></p> ++using the method described by Stephen Park and Keith Miller:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(stream-iterate ++<p align="justify"><pre><font face="monospace"> ++(stream-iterate + (lambda (x) (modulo (* x 16807) 2147483647)) +- </font><font face="serif"><i>seed</i></font><font face="monospace">)</font></font></font></pre><p></p> ++ </font><font face="serif"><i>seed</i></font><font face="monospace">)</font></pre></p> + +-<p><font face="serif"><font face="serif"><font face="serif">Successive values of the continued +-fraction shown below approach the value of the “golden ratio” φ +-≈ 1.618:</font></font></font></p> ++<p><font face="serif">Successive values of the continued ++fraction shown below approach the value of the “golden ratio” φ ++≈ 1.618:</font></p> + +-<p align="center"><font face="serif"><font face="serif"><img src="srfi-41_files/streams1.jpg" alt="Continued fraction" height="126" width="131"></font></font></p> ++<p align="center"><img alt="Continued fraction" height="126" src="streams1.jpg" width="131" /></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The fractions +-can be calculated by the stream</font></font></font></p> ++<p align="justify"><font face="serif">The fractions ++can be calculated by the stream</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-iterate +-(lambda (x) (+ 1 (/ x))) 1)</font></font></font></p> ++<p align="justify"><font face="monospace">(stream-iterate ++(lambda (x) (+ 1 (/ x))) 1)</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-length </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">{α} → nat</font><br> ++<p align="justify" id="stream-length"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-length </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">{α} → nat</font><br /> + <font face="monospace">Stream-length</font><font face="serif"> takes an input <i>stream</i> and returns + the number of elements in the <i>stream</i>; it does not evaluate its + elements. </font><font face="monospace">Stream-length</font><font face="serif"> may only be used on finite streams; +-it enters an infinite loop with infinite streams.</font></font></font></p> ++it enters an infinite loop with infinite streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-length +-strm123) </font><font face="Symbol">⇒</font><font face="monospace"> +-3</font></font></font></p> ++<p align="justify"><font face="monospace">(stream-length ++strm123) </font><font face="Symbol">⇒</font><font face="monospace"> ++3</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>syntax: </b></font> ++<p align="justify" id="stream-let"><font face="serif"><b>syntax: </b></font> + <font face="monospace"><b>(stream-let </b></font><font face="serif"><b><i>tag</i></b></font><font face="monospace"><b> +-((</b></font><font face="serif"><b><i>var</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>expr</i></b></font><font face="monospace"><b>) ...) </b></font><font face="serif"><b><i>body</i></b></font><font face="monospace"><b>)</b></font><br> ++((</b></font><font face="serif"><b><i>var</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>expr</i></b></font><font face="monospace"><b>) ...) </b></font><font face="serif"><b><i>body</i></b></font><font face="monospace"><b>)</b></font><br /> + <font face="monospace">Stream-let</font><font face="serif"> creates a local scope that binds each <i> + var</i>iable<i> </i>to the value of its corresponding <i>expr</i>ession. + It additionally binds <i>tag</i> to a procedure which takes the bound <i> +@@ -662,52 +701,55 @@ body</i>, and may be called recursively. When the expanded expression + defined by the </font><font face="monospace">stream-let</font><font face="serif"> is evaluated, </font><font face="monospace">stream-let</font><font face="serif"> evaluates the expressions in its <i> + body</i> in an environment containing the newly-bound <i>var</i>iables, + returning the value of the last expression evaluated, which must yield +-a stream.</font></font></font></p> ++a stream.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-let</font><font face="serif"> provides syntactic sugar on </font><font face="monospace">stream-lambda</font><font face="serif">, ++<p align="justify"><font face="monospace">Stream-let</font><font face="serif"> provides syntactic sugar on </font><font face="monospace">stream-lambda</font><font face="serif">, + in the same manner as normal </font><font face="monospace">let</font><font face="serif"> provides syntactic sugar on normal </font><font face="monospace">lambda</font><font face="serif">. + However, unlike normal </font><font face="monospace">let</font><font face="serif">, the <i>tag</i> is required, not optional, +-because unnamed </font><font face="monospace">stream-let</font><font face="serif"> is meaningless. </font></font></font></p> ++because unnamed </font><font face="monospace">stream-let</font><font face="serif"> is meaningless. </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-member</font><font face="serif"> returns the first stream-pair of the ++<p align="justify"><font face="monospace">Stream-member</font><font face="serif"> returns the first stream-pair of the + input </font><font face="monospace">strm</font><font face="serif"> +-with a </font><font face="monospace">stream-car</font><font face="serif"> <i>x</i> that satisfies </font><font face="monospace">(eql? obj </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif">.</font></font></font></p> ++with a </font><font face="monospace">stream-car</font><font face="serif"> <i>x</i> that satisfies </font><font face="monospace">(eql? obj </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif">, ++or the null stream if <i>x</i> is not present in </font><font face="monospace">strm</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-member eql? obj strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-member eql? obj strm) + (stream-let loop ((strm strm)) +- (cond ((stream-null? strm) #f) ++ (cond ((stream-null? strm) strm) + ((eql? obj (stream-car strm)) strm) +- (else (loop (stream-cdr strm))))))</pre></font></font></font></p> ++ (else (loop (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-map </b></font><font face="serif"><b><i>proc stream</i> </b></font><font face="monospace"><b>...)</b></font><br> +-<font face="monospace">(α × β ... → ω) × {α} × {β} ... → {ω}</font><br> ++<p align="justify" id="stream-map"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-map </b></font><font face="serif"><b><i>proc stream</i> </b></font><font face="monospace"><b>...)</b></font><br /> ++<font face="monospace">(α × β ... → ω) × {α} × {β} ... → {ω}</font><br /> + <font face="monospace">Stream-map</font><font face="serif"> applies a <i>proc</i>edure element-wise + to corresponding elements of the input <i>stream</i>s, returning a newly-allocated + stream containing elements that are the results of those <i>proc</i>edure + applications. The output stream has as many elements as the minimum-length +-input <i>stream</i>, and may be infinite.</font></font></font></p> ++input <i>stream</i>, and may be infinite.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define (square +-x) (* x x))</font></font></font></p> ++<p align="justify"><font face="monospace">(define (square ++x) (* x x))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-map square +-(stream 9 3)) ⇒ 81 9</font></font></font></p> ++<p align="justify"><font face="monospace">(stream-map square ++(stream 9 3)) ⇒ 81 9</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (sigma f m n) ++<p align="justify"><font face="monospace"><pre> ++(define (sigma f m n) + (stream-fold + 0 +- (stream-map f (stream-range m (+ n 1)))))</pre></font></font></font></p> ++ (stream-map f (stream-range m (+ n 1)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(sigma square 1 +-100) ⇒ 338350</font></font></font></p> ++<p align="justify"><font face="monospace">(sigma square 1 ++100) ⇒ 338350</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">In some functional ++<p align="justify"><font face="serif">In some functional + languages, </font><font face="monospace">stream-map</font><font face="serif"> takes only a single input stream, + and </font><font face="monospace">stream-zipwith</font><font face="serif"> provides a companion function that +-takes multiple input streams.</font></font></font></p> ++takes multiple input streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>syntax: </b></font> +-<font face="monospace"><b>(stream-match </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>clause</i></b></font><font face="monospace"><b> ...)</b></font><br> ++<p align="justify" id="stream-match"><font face="serif"><b>syntax: </b></font> ++<font face="monospace"><b>(stream-match </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>clause</i></b></font><font face="monospace"><b> ...)</b></font><br /> + <font face="monospace">Stream-match</font><font face="serif"> provides the syntax of pattern-matching + for streams. The input <i>stream</i> is an expression that evaluates + to a stream. Clauses are of the form </font><font face="monospace">(</font><font face="serif"><i>pattern</i></font><font face="monospace"> +@@ -715,66 +757,69 @@ to a stream. Clauses are of the form </font><font face="monospace">(</font><fon + consisting of a <i>pattern</i> that matches a stream of a particular + shape, an optional <i>fender</i> that must succeed if the pattern is + to match, and an <i>expr</i>ession that is evaluated if the <i>pattern</i> +-matches. There are four types of <i>pattern</i>s:</font></font></font></p> ++matches. There are four types of <i>pattern</i>s:</font></p> + +-<ul type="disc"> +-<font face="serif"><font face="serif"> <li><font face="monospace">()</font><font face="serif"> +- — Matches the null stream.</font></li> ++<ul type="DISC"> ++ <li><font face="monospace">()</font><font face="serif"> ++ — Matches the null stream.</font></li> + <li><font face="monospace">(</font><font face="serif"><i>pat</i><sub><i>0</i></sub></font><font face="monospace"> </font><font face="serif"><i>pat</i><sub><i>1</i></sub></font><font face="monospace"> ...)</font><font face="serif"> +- — Matches a finite stream with length exactly equal to the number ++ — Matches a finite stream with length exactly equal to the number + of pattern elements.</font></li> + <li><font face="monospace">(</font><font face="serif"><i>pat</i><sub><i>0</i></sub></font><font face="monospace"> </font><font face="serif"><i>pat</i><sub><i>1</i></sub></font><font face="monospace"> ... . </font><font face="serif"><i>pat</i><sub><i>rest</i></sub></font><font face="monospace">)</font><font face="serif"> +- — Matches an infinite stream, or a finite stream with length at least ++ — Matches an infinite stream, or a finite stream with length at least + as great as the number of pattern elements before the literal dot.</font></li> +- <li><font face="serif"><i>pat</i> — Matches ++ <li><font face="serif"><i>pat</i> — Matches + an entire stream. Should always appear last in the list of clauses; +- it’s not an error to appear elsewhere, but subsequent clauses could ++ it’s not an error to appear elsewhere, but subsequent clauses could + never match.</font></li> +-</font></font></ul> ++</ul> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Each pattern +-element <i>pat</i><sub><i>i</i></sub> may be either:</font></font></font></p> ++<p align="justify"><font face="serif">Each pattern ++element <i>pat</i><sub><i>i</i></sub> may be either:</font></p> + +-<ul type="disc"> +-<font face="serif"><font face="serif"> <li><font face="serif">An identifier — ++<ul type="DISC"> ++ <li><font face="serif">An identifier — + Matches any stream element. Additionally, the value of the stream + element is bound to the variable named by the identifier, which is in + scope in the <i>fender</i> and <i>expr</i>ession of the corresponding <i>clause</i>. + Each identifier in a single pattern must be unique.</font></li> + <li><font face="serif">A literal underscore +- — Matches any stream element, but creates no bindings.</font></li> +-</font></font></ul> ++ — Matches any stream element, but creates no bindings.</font></li> ++</ul> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The <i>pattern</i>s ++<p align="justify"><font face="serif">The <i>pattern</i>s + are tested in order, left-to-right, until a matching pattern is found; + if <i>fender</i> is present, it must evaluate as non-</font><font face="monospace">#f</font><font face="serif"> for the match to be successful. + Pattern variables are bound in the corresponding <i>fender</i> and <i> + expr</i>ession. Once the matching pattern is found, the corresponding <i> + expr</i>ession is evaluated and returned as the result of the match. +-An error is signaled if no pattern matches the input <i>stream</i>.</font></font></font></p> ++An error is signaled if no pattern matches the input <i>stream</i>.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-match</font><font face="serif"> is often used to distinguish null +-streams from non-null streams, binding </font><font face="monospace">head</font><font face="serif"> and </font><font face="monospace">tail</font><font face="serif">:</font></font></font></p> ++<p align="justify"><font face="monospace">Stream-match</font><font face="serif"> is often used to distinguish null ++streams from non-null streams, binding </font><font face="monospace">head</font><font face="serif"> and </font><font face="monospace">tail</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (len strm) ++<p align="justify"><font face="monospace"><pre> ++(define (len strm) + (stream-match strm + (() 0) +- ((head . tail) (+ 1 (len tail)))))</pre></font></font></font></p> ++ ((head . tail) (+ 1 (len tail)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Fenders can ++<p align="justify"><font face="serif">Fenders can + test the common case where two stream elements must be identical; the </font><font face="monospace">else</font><font face="serif"> + pattern is an identifier bound to the entire stream, not a keyword as +-in </font><font face="monospace">cond</font><font face="serif">.</font></font></font></p> ++in </font><font face="monospace">cond</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-match strm ++<p align="justify"><font face="monospace"><pre> ++(stream-match strm + ((x y . _) (equal? x y) 'ok) +- (else 'error))</pre></font></font></font></p> ++ (else 'error))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">A more complex ++<p align="justify"><font face="serif">A more complex + example uses two nested matchers to match two different stream arguments; </font><font face="monospace">(stream-merge lt? . </font><font face="serif"><i>strms</i></font><font face="monospace">)</font><font face="serif"> +-stably merges two or more streams ordered by the </font><font face="monospace">lt?</font><font face="serif"> predicate:</font></font></font></p> ++stably merges two or more streams ordered by the </font><font face="monospace">lt?</font><font face="serif"> predicate:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-merge lt? . strms) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-merge lt? . strms) + (define-stream (merge xx yy) + (stream-match xx (() yy) ((x . xs) + (stream-match yy (() xx) ((y . ys) +@@ -786,34 +831,34 @@ stably merges two or more streams ordered by the </font><font face="monospace">l + ((null? (cdr strms)) (car strms)) + (else (merge (car strms) + (apply stream-merge lt? +- (cdr strms)))))))</pre></font></font></font></p> ++ (cdr strms)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>syntax: </b></font> +-<font face="monospace"><b>(stream-of </b></font><font face="serif"><b><i>expr</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>clause</i></b></font><font face="monospace"><b> ...)</b></font><br> ++<p align="justify" id="stream-of"><font face="serif"><b>syntax: </b></font> ++<font face="monospace"><b>(stream-of </b></font><font face="serif"><b><i>expr</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>clause</i></b></font><font face="monospace"><b> ...)</b></font><br /> + <font face="monospace">Stream-of</font><font face="serif"> provides the syntax of stream comprehensions, + which generate streams by means of looping expressions. The result + is a stream of objects of the type returned by <i>expr</i>. There +-are four types of clauses:</font></font></font></p> ++are four types of clauses:</font></p> + +-<ul type="disc"> +-<font face="serif"><font face="serif"> <li><font face="monospace">(</font><font face="serif"><i>var</i></font><font face="monospace"> in </font><font face="serif"><i>stream-expr</i></font><font face="monospace">)</font><font face="serif"> +- — Loop over the elements of <i>stream-expr</i>, in order from the ++<ul type="DISC"> ++ <li><font face="monospace">(</font><font face="serif"><i>var</i></font><font face="monospace"> in </font><font face="serif"><i>stream-expr</i></font><font face="monospace">)</font><font face="serif"> ++ — Loop over the elements of <i>stream-expr</i>, in order from the + start of the stream, binding each element of the stream in turn to <i> + var</i>. </font><font face="monospace">Stream-from</font><font face="serif"> and </font><font face="monospace">stream-range</font><font face="serif"> are frequently useful as generators + for <i>stream-expr</i>.</font></li> + <li><font face="monospace">(</font><font face="serif"><i>var</i></font><font face="monospace"> is </font><font face="serif"><i>expr</i></font><font face="monospace">)</font><font face="serif"> +- — Bind <i>var</i> to the value obtained by evaluating <i>expr</i>.</font></li> ++ — Bind <i>var</i> to the value obtained by evaluating <i>expr</i>.</font></li> + <li><font face="monospace">(pred? </font><font face="serif"><i>expr</i></font><font face="monospace">)</font><font face="serif"> +- — Include in the output stream only those elements <i>x</i> for which </font><font face="monospace">(pred? </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif"> ++ — Include in the output stream only those elements <i>x</i> for which </font><font face="monospace">(pred? </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif"> + is non-</font><font face="monospace">#f</font><font face="serif">.</font></li> +-</font></font></ul> ++</ul> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The scope of <i> ++<p align="justify"><font face="serif">The scope of <i> + var</i>iables bound in the stream comprehension is the clauses to the + right of the binding clause (but not the binding clause itself) plus +-the result expression.</font></font></font></p> ++the result expression.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">When two or ++<p align="justify"><font face="serif">When two or + more generators are present, the loops are processed as if they are + nested from left to right; that is, the rightmost generator varies fastest. + A consequence of this is that only the first generator may be infinite +@@ -821,27 +866,30 @@ and all subsequent generators must be finite. If no generators + are present, the result of a stream comprehension is a stream containing + the result expression; thus, </font><font face="monospace">(stream-of + 1)</font><font face="serif"> produces a finite stream +-containing only the element </font><font face="monospace">1</font><font face="serif">.</font></font></font></p> ++containing only the element </font><font face="monospace">1</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-of (* x x) ++<p align="justify"><font face="monospace"><pre> ++(stream-of (* x x) + (x in (stream-range 0 10)) + (even? x)) +- ⇒ 0 4 16 36 64</pre></font></font></font></p> ++ ⇒ 0 4 16 36 64</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-of (list a b) ++<p align="justify"><font face="monospace"><pre> ++(stream-of (list a b) + (a in (stream-range 1 4)) + (b in (stream-range 1 3))) +- ⇒ (1 1) (1 2) (2 1) (2 2) (3 1) (3 2)</pre></font></font></font></p> ++ ⇒ (1 1) (1 2) (2 1) (2 2) (3 1) (3 2)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-of (list i j) ++<p align="justify"><font face="monospace"><pre> ++(stream-of (list i j) + (i in (stream-range 1 5)) + (j in (stream-range (+ i 1) 5))) +- ⇒ (1 2) (1 3) (1 4) (2 3) (2 4) (3 4)</pre></font></font></font></p> ++ ⇒ (1 2) (1 3) (1 4) (2 3) (2 4) (3 4)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> ++<p align="justify" id="stream-range"><font face="serif"><b>procedure: </b></font> + <font face="monospace"><b>(stream-range </b></font><font face="serif"><b><i>first</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>past</i></b></font><font face="monospace"><b> +-[</b></font><font face="serif"><b><i>step</i></b></font><font face="monospace"><b>])</b></font><br> +-<font face="monospace">number × number × number → {number}</font><br> ++[</b></font><font face="serif"><b><i>step</i></b></font><font face="monospace"><b>])</b></font><br /> ++<font face="monospace">number × number × number → {number}</font><br /> + <font face="monospace">Stream-range</font><font face="serif"> creates a newly-allocated stream that + contains <i>first</i> as its first element and increments each succeeding + element by <i>step</i>. The stream is finite and ends before <i> +@@ -852,170 +900,179 @@ otherwise. <i>First</i>, <i>past</i> and <i>step</i> may be of + any numeric type. </font><font face="monospace">Stream-range</font><font face="serif"> is frequently useful as a generator + in </font><font face="monospace">stream-of</font><font face="serif"> + expressions. See also </font><font face="monospace">stream-from</font><font face="serif"> for a similar procedure that creates +-infinite streams.</font></font></font></p> ++infinite streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-range 0 +-10) ⇒ 0 1 2 3 4 5 6 7 8 9</font></font></font></p> ++<p align="justify"><font face="monospace">(stream-range 0 ++10) ⇒ 0 1 2 3 4 5 6 7 8 9</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream-range 0 +-10 2) → 0 2 4 6 8</font></font></font></p> ++<p align="justify"><font face="monospace">(stream-range 0 ++10 2) → 0 2 4 6 8</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Successive ++<p align="justify"><font face="serif">Successive + elements of the stream are calculated by adding <i>step</i> to <i>first</i>, + so if any of <i>first</i>, <i>past</i> or <i>step</i> are inexact, the + length of the output stream may differ from </font><font face="monospace">(ceiling +-(- (/ (- </font><font face="serif"><i>past</i></font><font face="monospace"> </font><font face="serif"><i>first</i></font><font face="monospace">) </font><font face="serif"><i>step</i></font><font face="monospace">) 1)</font><font face="serif">.</font></font></font></p> ++(- (/ (- </font><font face="serif"><i>past</i></font><font face="monospace"> </font><font face="serif"><i>first</i></font><font face="monospace">) </font><font face="serif"><i>step</i></font><font face="monospace">) 1)</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-ref </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">{α} × nat → α</font><br> ++<p align="justify" id="stream-ref"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-ref </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">{α} × nat → α</font><br /> + <font face="monospace">Stream-ref</font><font face="serif"> returns the <i>n</i>th element of <i> + stream</i>, counting from zero. An error is signaled if <i>n</i> +-is greater than or equal to the length of <i>stream</i>.</font><font face="monospace"> </font></font></font></p> ++is greater than or equal to the length of <i>stream</i>.</font><font face="monospace"> </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (fact n) ++<p align="justify"><font face="monospace"><pre> ++(define (fact n) + (stream-ref + (stream-scan * 1 (stream-from 1)) +- n))</pre></font></font></font></p> ++ n))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-reverse </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">{α} → {α}</font><br> ++<p align="justify" id="stream-reverse"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-reverse </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">{α} → {α}</font><br /> + <font face="monospace">Stream-reverse</font><font face="serif"> returns a newly-allocated stream containing + the elements of the input <i>stream</i> but in reverse order. </font><font face="monospace">Stream-reverse</font><font face="serif"> + may only be used with finite streams; it enters an infinite loop with + infinite streams. </font><font face="monospace">Stream-reverse</font><font face="serif"> does not force evaluation of the elements +-of the stream.</font></font></font></p> ++of the stream.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>> (define s (stream 1 (/ 1 0) -1)) ++<p align="justify"><font face="monospace"><pre> ++> (define s (stream 1 (/ 1 0) -1)) + > (define r (stream-reverse s)) + > (stream-ref r 0) + > (stream-ref r 2) + 1 + > (stream-ref r 1) +-error: division by zero</pre></font></font></font></p> ++error: division by zero</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-scan </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α × β → α) × α × {β} → {α}</font><br> ++<p align="justify" id="stream-scan"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-scan </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α × β → α) × α × {β} → {α}</font><br /> + <font face="monospace">Stream-scan</font><font face="serif"> accumulates the partial folds of an + input <i>stream</i> into a newly-allocated output stream. The + output stream is the <i>base</i> followed by </font><font face="monospace">(stream-fold + proc base (stream-take </font><font face="serif"><i>i</i></font><font face="monospace"> stream))</font><font face="serif"> +-for each of the first <i>i</i> elements of <i>stream</i>.</font></font></font></p> ++for each of the first <i>i</i> elements of <i>stream</i>.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-scan + 0 (stream-from 1)) +- ⇒ (stream 0 1 3 6 10 15 ...)</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-scan + 0 (stream-from 1)) ++ ⇒ (stream 0 1 3 6 10 15 ...)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-scan * 1 (stream-from 1)) +- ⇒ (stream 1 1 2 6 24 120 ...)</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-scan * 1 (stream-from 1)) ++ ⇒ (stream 1 1 2 6 24 120 ...)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-take </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">nat × {α} → {α}</font><br> ++<p align="justify" id="stream-take"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-take </b></font><font face="serif"><b><i>n</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">nat × {α} → {α}</font><br /> + <font face="monospace">Stream-take</font><font face="serif"> takes a non-negative integer <i>n</i> + and a <i>stream</i> and returns a newly-allocated stream containing + the first <i>n</i> elements of the input <i>stream</i>. If the + input <i>stream</i> has less than <i>n</i> elements, so does the output +-stream. See also </font><font face="monospace">stream-drop</font><font face="serif">.</font></font></font></p> ++stream. See also </font><font face="monospace">stream-drop</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Mergesort splits ++<p align="justify"><font face="serif">Mergesort splits + a stream into two equal-length pieces, sorts them recursively and merges +-the results:</font></font></font></p> ++the results:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (msort lt? strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (msort lt? strm) + (let* ((n (quotient (stream-length strm) 2)) + (ts (stream-take n strm)) + (ds (stream-drop n strm))) + (if (zero? n) + strm + (stream-merge lt? +- (msort < ts) (msort < ds)))))</pre></font></font></font></p> ++ (msort < ts) (msort < ds)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-take-while </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α → boolean) × {α} → {α}</font><br> ++<p align="justify" id="stream-take-while"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-take-while </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α → boolean) × {α} → {α}</font><br /> + <font face="monospace">Stream-take-while</font><font face="serif"> takes a predicate and a <i>stream</i> + and returns a newly-allocated stream containing those elements <i>x</i> + that form the maximal prefix of the input <i>stream</i> for which </font><font face="monospace">(pred? </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif"> + is non-</font><font face="monospace">#f</font><font face="serif">. +-See also </font><font face="monospace">stream-drop-while</font><font face="serif">.</font></font></font></p> ++See also </font><font face="monospace">stream-drop-while</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-car ++<p align="justify"><font face="monospace"><pre> ++(stream-car + (stream-reverse + (stream-take-while + (lambda (x) (< x 1000)) +- primes))) ⇒ 997</pre></font></font></font></p> ++ primes))) ⇒ 997</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-unfold </b></font><font face="serif"><b><i>map</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>gen</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i>)</b></font><br> +-<font face="monospace">(α → β) × (α → boolean) × (α → α) × α → {β}</font><br> ++<p align="justify" id="stream-unfold"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-unfold </b></font><font face="serif"><b><i>map</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>gen</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>base</i>)</b></font><br /> ++<font face="monospace">(α → β) × (α → boolean) × (α → α) × α → {β}</font><br /> + <font face="monospace">Stream-unfold</font><font face="serif"> is the fundamental recursive stream + constructor. It constructs a stream by repeatedly applying <i> + gen</i> to successive values of <i>base</i>, in the manner of </font><font face="monospace">stream-iterate</font><font face="serif">, + then applying <i>map</i> to each of the values so generated, appending + each of the mapped values to the output stream as long as </font><font face="monospace">(</font><font face="serif"><i>pred?</i></font><font face="monospace"> </font><font face="serif"><i>base</i></font><font face="monospace">)</font><font face="serif"> + is non-</font><font face="monospace">#f</font><font face="serif">. +-See also </font><font face="monospace">stream-iterate</font><font face="serif"> and </font><font face="monospace">stream-unfolds</font><font face="serif">.</font></font></font></p> ++See also </font><font face="monospace">stream-iterate</font><font face="serif"> and </font><font face="monospace">stream-unfolds</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The expression ++<p align="justify"><font face="serif">The expression + below creates the finite stream </font><font face="monospace">0</font><font face="serif"> </font><font face="monospace">1</font><font face="serif"> </font><font face="monospace">4</font><font face="serif"> </font><font face="monospace">9</font><font face="serif"> </font><font face="monospace">16</font><font face="serif"> </font><font face="monospace">25</font><font face="serif"> </font><font face="monospace">36</font><font face="serif"> </font><font face="monospace">49</font><font face="serif"> </font><font face="monospace">64</font><font face="serif"> </font><font face="monospace">81</font><font face="serif">. Initially the </font><font face="monospace">base</font><font face="serif"> is </font><font face="monospace">0</font><font face="serif">, which is less than </font><font face="monospace">10</font><font face="serif">, so <i>map</i> squares the <i>base</i> + and the mapped value becomes the first element of the output stream. + Then <i>gen</i> increments the <i>base</i> by </font><font face="monospace">1</font><font face="serif">, so it becomes </font><font face="monospace">1</font><font face="serif">; this is less than </font><font face="monospace">10</font><font face="serif">, so <i>map</i> squares the new </font><font face="monospace">base</font><font face="serif"> + and </font><font face="monospace">1</font><font face="serif"> + becomes the second element of the output stream. And so on, until + the <i>base</i> becomes </font><font face="monospace">10</font><font face="serif">, when <i>pred?</i> stops the recursion +-and </font><font face="monospace">stream-null</font><font face="serif"> ends the output stream.</font></font></font></p> ++and </font><font face="monospace">stream-null</font><font face="serif"> ends the output stream.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-unfold ++<p align="justify"><font face="monospace"><pre> ++(stream-unfold + (lambda (x) (expt x 2)) ; map + (lambda (x) (< x 10)) ; pred? + (lambda (x) (+ x 1)) ; gen +- 0) ; base</pre></font></font></font></p> ++ 0) ; base</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-unfolds </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>seed</i></b></font><font face="monospace"><b>)</b></font><br> +-<font face="monospace">(α → (values α × β ...)) × α → (values {β} ...)</font><br> ++<p align="justify"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-unfolds </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>seed</i></b></font><font face="monospace"><b>)</b></font><br /> ++<font face="monospace">(α → (values α × β ...)) × α → (values {β} ...)</font><br /> + <font face="monospace">Stream-unfolds</font><font face="serif"> returns <i>n</i> newly-allocated streams + containing those elements produced by successive calls to the generator <i> + proc</i>, which takes the current <i>seed</i> as its argument and returns <i> + n</i></font><font face="monospace">+1</font><font face="serif"> +-values</font></font></font></p> ++values</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(</font><font face="serif"><i>proc</i></font><font face="monospace"> </font><font face="serif"><i>seed</i></font> → <font face="serif"><i>seed</i></font><font face="monospace"> </font><font face="serif"><i>result</i><sub><i>0</i></sub></font><font face="monospace"> ... </font><font face="serif"><i>result</i><sub><i>n-1</i></sub></font></font></font></p> ++<p align="justify"><font face="monospace">(</font><font face="serif"><i>proc</i></font><font face="monospace"> </font><font face="serif"><i>seed</i></font> → <font face="serif"><i>seed</i></font><font face="monospace"> </font><font face="serif"><i>result</i><sub><i>0</i></sub></font><font face="monospace"> ... </font><font face="serif"><i>result</i><sub><i>n-1</i></sub></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">where the returned <i> ++<p align="justify"><font face="serif">where the returned <i> + seed</i> is the input <i>seed</i> to the next call to the generator + and <i>result</i><sub><i>i</i></sub> indicates how to produce the next +-element of the <i>i</i><sup><i>th</i></sup> result stream:</font></font></font></p> ++element of the <i>i</i><sup><i>th</i></sup> result stream:</font></p> + +-<ul type="disc"> +-<font face="serif"><font face="serif"> <li><font face="monospace">(</font><font face="serif"><i>value</i></font><font face="monospace">)</font><font face="serif"> +- — <i>value</i> is the next car of the result stream</font></li> ++<ul type="DISC"> ++ <li><font face="monospace">(</font><font face="serif"><i>value</i></font><font face="monospace">)</font><font face="serif"> ++ — <i>value</i> is the next car of the result stream</font></li> + <li><font face="monospace">#f</font><font face="serif"> +- — no value produced by this iteration of the generator <i>proc</i> ++ — no value produced by this iteration of the generator <i>proc</i> + for the result stream</font></li> + <li><font face="monospace">()</font><font face="serif"> +- — the end of the result stream</font></li> +-</font></font></ul> ++ — the end of the result stream</font></li> ++</ul> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It may require ++<p align="justify"><font face="serif">It may require + multiple calls of <i>proc</i> to produce the next element of any particular +-result stream. See also </font><font face="monospace">stream-iterate</font><font face="serif"> and </font><font face="monospace">stream-unfold</font><font face="serif">.</font></font></font></p> ++result stream. See also </font><font face="monospace">stream-iterate</font><font face="serif"> and </font><font face="monospace">stream-unfold</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-unfolds</font><font face="serif"> is especially useful when writing ++<p align="justify"><font face="monospace">Stream-unfolds</font><font face="serif"> is especially useful when writing + expressions that return multiple streams. For instance, </font><font face="monospace">(stream-partition </font><font face="serif"><i>pred?</i></font><font face="monospace"> </font><font face="serif"><i>strm</i></font><font face="monospace">)</font><font face="serif"> +-is equivalent to</font></font></font></p> ++is equivalent to</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(values ++<p align="justify"><pre><font face="monospace"> ++(values + (stream-filter </font><font face="serif"><i>pred?</i></font><font face="monospace"> </font><font face="serif"><i>strm</i></font><font face="monospace">) + (stream-filter +- (lambda (x) (not (</font><font face="serif"><i>pred?</i></font><font face="monospace"> x))) </font><font face="serif"><i>strm</i></font><font face="monospace">))</font></font></font></pre><p></p> ++ (lambda (x) (not (</font><font face="serif"><i>pred?</i></font><font face="monospace"> x))) </font><font face="serif"><i>strm</i></font><font face="monospace">))</font></pre></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">but only tests <i> +-pred?</i> once for each element of <i>strm</i>.</font></font></font></p> ++<p align="justify"><font face="serif">but only tests <i> ++pred?</i> once for each element of <i>strm</i>.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-partition pred? strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-partition pred? strm) + (stream-unfolds + (lambda (s) + (if (stream-null? s) +@@ -1025,95 +1082,102 @@ pred?</i> once for each element of <i>strm</i>.</font></font></font></p> + (if (pred? a) + (values d (list a) #f) + (values d #f (list a)))))) +- strm))</pre></font></font></font></p> ++ strm))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(call-with-values ++<p align="justify"><font face="monospace"><pre> ++(call-with-values + (lambda () + (stream-partition odd? + (stream-range 1 6))) + (lambda (odds evens) + (list (stream->list odds) + (stream->list evens)))) +- ⇒ ((1 3 5) (2 4))</font></font></font></pre><p></p> ++ ⇒ ((1 3 5) (2 4))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><b>procedure: </b></font> +-<font face="monospace"><b>(stream-zip </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br> +-<font face="monospace">{α} × {β} × ... → {[α β ...]}</font><br> ++<p align="justify" id="stream-zip"><font face="serif"><b>procedure: </b></font> ++<font face="monospace"><b>(stream-zip </b></font><font face="serif"><b><i>stream</i></b></font><font face="monospace"><b> ...)</b></font><br /> ++<font face="monospace">{α} × {β} × ... → {[α β ...]}</font><br /> + <font face="monospace">Stream-zip</font><font face="serif"> takes one or more input <i>stream</i>s + and returns a newly-allocated stream in which each element is a list + (not a stream) of the corresponding elements of the input <i>stream</i>s. + The output stream is as long as the shortest input <i>stream</i>, if + any of the input <i>stream</i>s is finite, or is infinite if all the +-input <i>stream</i>s are infinite.</font></font></font></p> ++input <i>stream</i>s are infinite.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">A common use ++<p align="justify"><font face="serif">A common use + of </font><font face="monospace">stream-zip</font><font face="serif"> + is to add an index to a stream, as in </font><font face="monospace">(stream-finds </font><font face="serif"><i>eql?</i></font><font face="monospace"> </font><font face="serif"><i>obj</i></font><font face="monospace"> </font><font face="serif"><i>strm</i></font><font face="monospace">)</font><font face="serif">, which returns all the zero-based + indices in <i>strm</i> at which <i>obj</i> appears; </font><font face="monospace">(stream-find </font><font face="serif"><i>eql?</i></font><font face="monospace"> </font><font face="serif"><i>obj</i></font><font face="monospace"> </font><font face="serif"><i>strm</i></font><font face="monospace">)</font><font face="serif"> returns the first such index, or </font><font face="monospace">#f</font><font face="serif"> +-if <i>obj</i> is not in <i>strm</i>.</font></font></font></p> ++if <i>obj</i> is not in <i>strm</i>.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-finds eql? obj strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-finds eql? obj strm) + (stream-of (car x) + (x in (stream-zip (stream-from 0) strm)) +- (eql? obj (cadr x))))</pre></font></font></font></p> ++ (eql? obj (cadr x))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-find eql? obj strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-find eql? obj strm) + (stream-car + (stream-append + (stream-finds eql? obj strm) +- (stream #f))))</pre></font></font></font></p> ++ (stream #f))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-find char=? #\l ++<p align="justify"><font face="monospace"><pre> ++(stream-find char=? #\l + (list->stream +- (string->list "hello"))) ⇒ 2</pre></font></font></font></p> ++ (string->list "hello"))) ⇒ 2</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-find char=? #\l ++<p align="justify"><font face="monospace"><pre> ++(stream-find char=? #\l + (list->stream +- (string->list "goodbye"))) ⇒ #f</pre></font></font></font></p> ++ (string->list "goodbye"))) ⇒ #f</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Stream-find</font><font face="serif"> is not as inefficient as it looks; ++<p align="justify"><font face="monospace">Stream-find</font><font face="serif"> is not as inefficient as it looks; + although it calls </font><font face="monospace">stream-finds</font><font face="serif">, which finds all matching indices, + the matches are computed lazily, and only the first match is needed +-for </font><font face="monospace">stream-find</font><font face="serif">.</font></font></font></p> ++for </font><font face="monospace">stream-find</font><font face="serif">.</font></p> + +-<h1><font face="serif"><font face="serif">Utilities</font></font></h1> ++<h2>Utilities</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Streams, being ++<p align="justify"><font face="serif">Streams, being + the signature structured data type of functional programming languages, + find useful expression in conjunction with higher-order functions. + Some of these higher-order functions, and their relationship to streams, +-are described below.</font></font></font></p> ++are described below.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The identity ++<p align="justify"><font face="serif">The identity + and constant procedures are frequently useful as the recursive base + for maps and folds; </font><font face="monospace"><b>(identity </b></font><font face="serif"><b><i>obj</i></b></font><font face="monospace"><b>)</b></font><font face="serif"> always returns <i>obj</i>, and </font><font face="monospace"><b>(const </b></font><font face="serif"><b><i>obj</i></b></font><font face="monospace"><b>)</b></font><font face="serif"> + creates a procedure that takes any number of arguments and always returns +-the same <i>obj</i>, no matter its arguments:</font></font></font></p> ++the same <i>obj</i>, no matter its arguments:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define (identity +-obj) obj)</font></font></font></p> ++<p align="justify"><font face="monospace">(define (identity ++obj) obj)</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define (const +-obj) (lambda x obj))</font></font></font></p> ++<p align="justify"><font face="monospace">(define (const ++obj) (lambda x obj))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Many of the ++<p align="justify"><font face="serif">Many of the + stream procedures take a unary predicate that accepts an element of + a stream and returns a boolean. Procedure </font><font face="monospace"><b>(negate </b></font><font face="serif"><b><i>pred?</i></b></font><font face="monospace"><b>)</b></font><font face="serif"> takes a unary predicate and returns + a new unary predicate that, when called, returns the opposite boolean +-value as the original predicate.</font></font></font></p> ++value as the original predicate.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (negate pred?) +- (lambda (x) (not (pred? x))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (negate pred?) ++ (lambda (x) (not (pred? x))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Negate</font><font face="serif"> is useful for procedures like </font><font face="monospace">stream-take-while</font><font face="serif"> ++<p align="justify"><font face="monospace">Negate</font><font face="serif"> is useful for procedures like </font><font face="monospace">stream-take-while</font><font face="serif"> + that take a predicate, allowing them to be used in the opposite direction + from which they were written; for instance, with the predicate reversed, </font><font face="monospace">stream-take-while</font><font face="serif"> +-becomes </font><font face="monospace">stream-take-until</font><font face="serif">. </font><font face="monospace">Stream-remove</font><font face="serif"> is the opposite of </font><font face="monospace">stream-filter</font><font face="serif">:</font></font></font></p> ++becomes </font><font face="monospace">stream-take-until</font><font face="serif">. </font><font face="monospace">Stream-remove</font><font face="serif"> is the opposite of </font><font face="monospace">stream-filter</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-remove pred? strm) +- (stream-filter (negate pred?) strm))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-remove pred? strm) ++ (stream-filter (negate pred?) strm))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">A section is ++<p align="justify"><font face="serif">A section is + a procedure which has been partially applied to some of its arguments; + for instance, </font><font face="monospace">(double </font><font face="serif"><i>x</i></font><font face="monospace">)</font><font face="serif">, which returns twice its argument, + is a partial application of the multiply operator to the number </font><font face="monospace">2</font><font face="serif">. +@@ -1125,34 +1189,37 @@ and some prefix of its arguments and returns a new procedure in which + those arguments are partially applied. Procedure </font><font face="monospace"><b>(rsec </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> </b></font><font face="serif"><b><i>args</i></b></font><font face="monospace"><b> + ...)</b></font><font face="serif"> takes a <i>proc</i>edure + and some reversed suffix of its arguments and returns a new procedure +-in which those arguments are partially applied.</font></font></font></p> ++in which those arguments are partially applied.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (lsec proc . args) +- (lambda x (apply proc (append args x))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (lsec proc . args) ++ (lambda x (apply proc (append args x))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (rsec proc . args) ++<p align="justify"><font face="monospace"><pre> ++(define (rsec proc . args) + (lambda x (apply proc (reverse +- (append (reverse args) (reverse x))))))</pre></font></font></font></p> ++ (append (reverse args) (reverse x))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Since most ++<p align="justify"><font face="serif">Since most + of the stream procedures take a stream as their last (right-most) argument, +-left sections are particularly useful in conjunction with streams.</font></font></font></p> ++left sections are particularly useful in conjunction with streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define stream-sum +-(lsec stream-fold + 0))</font></font></font></p> ++<p align="justify"><font face="monospace">(define stream-sum ++(lsec stream-fold + 0))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Function composition ++<p align="justify"><font face="serif">Function composition + creates a new function by partially applying multiple functions, one + after the other. In the simplest case there are only two functions, </font><font face="monospace">f</font><font face="serif"> + and </font><font face="monospace">g</font><font face="serif">, +-composed as </font><font face="monospace">((compose f g) ≡ <i>x</i></font><font face="monospace">))</font><font face="serif">; ++composed as </font><font face="monospace">((compose f g) ≡ <i>x</i></font><font face="monospace">))</font><font face="serif">; + the composition can be bound to create a new function, as in </font><font face="monospace">(define fg (compose f g))</font><font face="serif">. + Procedure </font><font face="monospace"><b>(compose </b></font><font face="serif"><b><i>proc</i></b></font><font face="monospace"><b> + ...)</b></font><font face="serif"> takes one or more <i> + proc</i>edures and returns a new procedure that performs the same action +-as the individual procedures would if called in succession.</font></font></font></p> ++as the individual procedures would if called in succession.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (compose . fns) ++<p align="justify"><font face="monospace"><pre> ++(define (compose . fns) + (let comp ((fns fns)) + (cond + ((null? fns) 'error) +@@ -1164,107 +1231,114 @@ as the individual procedures would if called in succession.</font></font></font> + (apply + (comp (cdr fns)) + args)) +- (car fns)))))))</pre></font></font></font></p> ++ (car fns)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Compose</font><font face="serif"> works with sections to create succinct ++<p align="justify"><font face="monospace">Compose</font><font face="serif"> works with sections to create succinct + but highly expressive procedure definitions. The expression to + compute the squares of the integers from </font><font face="monospace">1</font><font face="serif"> to </font><font face="monospace">10</font><font face="serif"> given above at </font><font face="monospace">stream-unfold</font><font face="serif"> could be written by composing </font><font face="monospace">stream-map</font><font face="serif">, </font><font face="monospace">stream-take-while</font><font face="serif">, +-and </font><font face="monospace">stream-iterate</font><font face="serif">:</font></font></font></p> ++and </font><font face="monospace">stream-iterate</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>((compose ++<p align="justify"><font face="monospace"><pre> ++((compose + (lsec stream-map (rsec expt 2)) + (lsec stream-take-while (negate (rsec > 10))) + (lsec stream-iterate (rsec + 1))) +- 1)</pre></font></font></font></p> ++ 1)</pre></font></p> + +-<h1><font face="serif"><font face="serif">Examples</font></font></h1> ++<h2>Examples</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The examples ++<p align="justify"><font face="serif">The examples + below show a few of the myriad ways streams can be exploited, as well + as a few ways they can trip the unwary user. All the examples + are drawn from published sources; it is instructive to compare the Scheme +-versions to the originals in other languages.</font></font></font></p> ++versions to the originals in other languages.</font></p> + +-<h2><font face="serif"><font face="serif">Infinite streams</font></font></h2> ++<h3>Infinite streams</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">As a simple ++<p align="justify"><font face="serif">As a simple + illustration of infinite streams, consider this definition of the natural +-numbers:</font></font></font></p> ++numbers:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define nats ++<p align="justify"><font face="monospace"><pre> ++(define nats + (stream-cons 0 +- (stream-map add1 nats)))</pre></font></font></font></p> ++ (stream-map add1 nats)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The recursion ++<p align="justify"><font face="serif">The recursion + works because it is offset by one from the initial </font><font face="monospace">stream-cons</font><font face="serif">. Another sequence that uses +-the offset trick is this definition of the fibonacci numbers:</font></font></font></p> ++the offset trick is this definition of the fibonacci numbers:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define fibs ++<p align="justify"><font face="monospace"><pre> ++(define fibs + (stream-cons 1 + (stream-cons 1 + (stream-map + + fibs +- (stream-cdr fibs)))))</pre></font></font></font></p> ++ (stream-cdr fibs)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Yet another ++<p align="justify"><font face="serif">Yet another + sequence that uses the same offset trick is the Hamming numbers, named + for the mathematician and computer scientist Richard Hamming, defined + as all numbers that have no prime factors greater than 5; in other words, +-Hamming numbers are all numbers expressible as 2<sup><i>i</i></sup>·3<sup><i>j</i></sup>·5<sup><i>k</i></sup>, ++Hamming numbers are all numbers expressible as 2<sup><i>i</i></sup>·3<sup><i>j</i></sup>·5<sup><i>k</i></sup>, + where <i>i</i>, <i>j</i> and <i>k</i> are non-negative integers. The + Hamming sequence starts with </font><font face="monospace">1 + 2 3 4 5 6 8 9 10 12</font><font face="serif"> and + is computed starting with </font><font face="monospace">1</font><font face="serif">, taking </font><font face="monospace">2</font><font face="serif">, </font><font face="monospace">3</font><font face="serif"> and </font><font face="monospace">5</font><font face="serif"> times all the previous elements with </font><font face="monospace">stream-map</font><font face="serif">, +-then merging sub-streams and eliminating duplicates.</font></font></font></p> ++then merging sub-streams and eliminating duplicates.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define hamming ++<p align="justify"><font face="monospace"><pre> ++(define hamming + (stream-cons 1 + (stream-unique = + (stream-merge < + (stream-map (lsec * 2) hamming) + (stream-map (lsec * 3) hamming) +- (stream-map (lsec * 5) hamming)))))</pre></font></font></font></p> ++ (stream-map (lsec * 5) hamming)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It is possible ++<p align="justify"><font face="serif">It is possible + to have an infinite stream of infinite streams. Consider the definition +-of </font><font face="monospace">power-table</font><font face="serif">:</font></font></font></p> ++of </font><font face="monospace">power-table</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define power-table ++<p align="justify"><font face="monospace"><pre> ++(define power-table + (stream-of + (stream-of (expt m n) + (m in (stream-from 1))) +- (n in (stream-from 2))))</pre></font></font></font></p> ++ (n in (stream-from 2))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">which evaluates +-to an infinite stream of infinite streams:</font></font></font></p> ++<p align="justify"><font face="serif">which evaluates ++to an infinite stream of infinite streams:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><mpre> ++<p align="justify"><font face="monospace"><pre> + (stream + (stream 1 4 9 16 25 ...) + (stream 1 8 27 64 125 ...) + (stream 1 16 81 256 625 ...) +- ...)</mpre></font></font></font></p> ++ ...)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">But even though ++<p align="justify"><font face="serif">But even though + it is impossible to display </font><font face="monospace">power-table</font><font face="serif"> in its entirety, it is possible to +-select just part of it:</font></font></font></p> ++select just part of it:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream->list 10 (stream-ref power-table 1)) +- ⇒ (1 8 27 64 125 216 343 512 729 1000)</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream->list 10 (stream-ref power-table 1)) ++ ⇒ (1 8 27 64 125 216 343 512 729 1000)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">This example ++<p align="justify"><font face="serif">This example + clearly shows that the elements of a stream are computed lazily, as + they are needed; </font><font face="monospace">(stream-ref + power-table 0)</font><font face="serif"> is not computed, + even when its successor is displayed, since computing it would enter +-an infinite loop.</font></font></font></p> ++an infinite loop.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Chris Reade ++<p align="justify"><font face="serif">Chris Reade + shows how to calculate the stream of prime numbers according to the + sieve of Eratosthenes, using a method that eliminates multiples of the +-sifting base with addition rather than division:</font></font></font></p> ++sifting base with addition rather than division:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define primes (let () ++<p align="justify"><font face="monospace"><pre> ++(define primes (let () + (define-stream (next base mult strm) + (let ((first (stream-car strm)) + (rest (stream-cdr strm))) +@@ -1282,32 +1356,33 @@ sifting base with addition rather than division:</font></font></font></p> + (rest (stream-cdr strm))) + (stream-cons first + (sieve (sift first rest))))) +- (sieve (stream-from 2))))</pre></font></font></font></p> ++ (sieve (stream-from 2))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">A final example ++<p align="justify"><font face="serif">A final example + of infinite streams is a functional pearl from Jeremy Gibbons, David + Lester and Richard Bird that enumerates the positive rational numbers +-without duplicates:</font></font></font></p> ++without duplicates:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define rats ++<p align="justify"><font face="monospace"><pre> ++(define rats + (stream-iterate + (lambda (x) + (let* ((n (floor x)) (y (- x n))) + (/ (- n -1 y)))) +- 1))</pre></font></font></font></p> ++ 1))</pre></font></p> + +-<h2><font face="serif"><font face="serif">Backtracking via the stream of successes</font></font></h2> ++<h3>Backtracking via the stream of successes</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Philip Wadler ++<p align="justify"><font face="serif">Philip Wadler + describes the <i>stream of successes</i> technique that uses streams + to perform backtracking search. The basic idea is that each procedure + returns a stream of possible results, so that its caller can decide + which result it wants; an empty stream signals failure, and causes backtracking + to a previous choice point. The stream of successes technique + is useful because the program is written as if to simply enumerate all +-possible solutions; no backtracking is explicit in the code.</font></font></font></p> ++possible solutions; no backtracking is explicit in the code.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The Eight Queens ++<p align="justify"><font face="serif">The Eight Queens + puzzle, which asks for a placement of eight queens on a chessboard so + that none of them attack any other, is an example of a problem that + can be solved using the stream of successes technique. The algorithm +@@ -1318,45 +1393,48 @@ Then a queen is placed in the third column, in any position not held + in check by the queens in the first two columns. And so on, until + all eight queens have been placed. If at any point there is no + legal placement for the next queen, backtrack to a different legal position +-for the previous queens, and try again.</font></font></font></p> ++for the previous queens, and try again.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The chessboard ++<p align="justify"><font face="serif">The chessboard + is represented as a stream of length <i>m</i>, where there are queens + in the first <i>m</i> columns, each position in the stream representing + the rank on which the queen appears in that column. For example, + stream </font><font face="monospace">4</font><font face="serif"> </font><font face="monospace">6</font><font face="serif"> </font><font face="monospace">1</font><font face="serif"> </font><font face="monospace">5</font><font face="serif"> </font><font face="monospace">2</font><font face="serif"> </font><font face="monospace">8</font><font face="serif"> </font><font face="monospace">3</font><font face="serif"> </font><font face="monospace">7</font><font face="serif"> +-represents the following chessboard:</font></font></font></p> ++represents the following chessboard:</font></p> + +-<p align="center"><font face="serif"><font face="serif"><img src="srfi-41_files/streams2.jpg" alt="Chessboard" height="205" width="195"></font></font></p> ++<p align="center"><img alt="Chessboard" height="205" src="streams2.jpg" width="195" /></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Two queens ++<p align="justify"><font face="serif">Two queens + at column <i>i</i> row <i>j</i> and column <i>m</i> row <i>n</i> check + each other if their columns <i>i</i> and <i>m</i> are the same, or if + their rows <i>j</i> and <i>n</i> are the same, or if they are on the + same diagonal with <i>i</i> + <i>j</i> = <i>m</i> + <i>n</i> or <i>i</i> +-– <i>j</i> = <i>m</i> – <i>n</i>. There is no need to test ++– <i>j</i> = <i>m</i> – <i>n</i>. There is no need to test + the columns, because the placement algorithm enforces that they differ, + so the </font><font face="monospace">check?</font><font face="serif"> +-procedure tests if two queens hold each other in check.</font></font></font></p> ++procedure tests if two queens hold each other in check.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (check? i j m n) ++<p align="justify"><font face="monospace"><pre> ++(define (check? i j m n) + (or (= j n) + (= (+ i j) (+ m n)) +- (= (- i j) (- m n))))</pre></font></font></font></p> ++ (= (- i j) (- m n))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The algorithm ++<p align="justify"><font face="serif">The algorithm + walks through the columns, extending position <i>p</i> by adding a new + queen in row <i>n</i> with </font><font face="monospace">(stream-append </font><font face="serif"><i>p</i></font><font face="monospace"> + (stream </font><font face="serif"><i>n</i></font><font face="monospace">))</font><font face="serif">. </font><font face="monospace">Safe?</font><font face="serif"> +-tests if it is safe to do so, using the utility procedure </font><font face="monospace">stream-and</font><font face="serif">.</font></font></font></p> ++tests if it is safe to do so, using the utility procedure </font><font face="monospace">stream-and</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-and strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-and strm) + (let loop ((strm strm)) + (cond ((stream-null? strm) #t) + ((not (stream-car strm)) #f) +- (else (loop (stream-cdr strm))))))</pre></font></font></font></p> ++ (else (loop (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (safe? p n) ++<p align="justify"><font face="monospace"><pre> ++(define (safe? p n) + (let* ((len (stream-length p)) + (m (+ len 1))) + (stream-and +@@ -1364,86 +1442,91 @@ tests if it is safe to do so, using the utility procedure </font><font face="mon + (not (check? (car ij) (cadr ij) m n)) + (ij in (stream-zip + (stream-range 1 m) +- p))))))</pre></font></font></font></p> ++ p))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Procedure </font><font face="monospace">(queens </font><font face="serif"><i>m</i></font><font face="monospace">)</font><font face="serif"> ++<p align="justify"><font face="serif">Procedure </font><font face="monospace">(queens </font><font face="serif"><i>m</i></font><font face="monospace">)</font><font face="serif"> + returns all the ways that queens can safely be placed in the first <i> +-m</i> columns.</font></font></font></p> ++m</i> columns.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queens m) ++<p align="justify"><font face="monospace"><pre> ++(define (queens m) + (if (zero? m) + (stream (stream)) + (stream-of (stream-append p (stream n)) + (p in (queens (- m 1))) + (n in (stream-range 1 9)) +- (safe? p n))))</pre></font></font></font></p> ++ (safe? p n))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">To see the +-first solution to the Eight Queens problem, say</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(stream->list +-(stream-car (queens 8)))</font></font></font></p> ++<p align="justify"><font face="serif">To see the ++first solution to the Eight Queens problem, say</font></p> ++<p align="justify"><font face="monospace">(stream->list ++(stream-car (queens 8)))</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">To see all +-92 solutions, say</font></font></font></p> ++<p align="justify"><font face="serif">To see all ++92 solutions, say</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream->list ++<p align="justify"><font face="monospace"><pre> ++(stream->list + (stream-map stream->list +- (queens 8)))</pre></font></font></font></p> ++ (queens 8)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">There is no ++<p align="justify"><font face="serif">There is no + explicit backtracking in the code. The </font><font face="monospace">stream-of</font><font face="serif"> expression in </font><font face="monospace">queens</font><font face="serif"> returns all possible streams that + satisfy </font><font face="monospace">safe?</font><font face="serif">; +-implicit backtracking occurs in the recursive call to </font><font face="monospace">queens</font><font face="serif">.</font></font></font></p> ++implicit backtracking occurs in the recursive call to </font><font face="monospace">queens</font><font face="serif">.</font></p> + +-<h2><font face="serif"><font face="serif">Generators and co-routines</font></font></h2> ++<h3>Generators and co-routines</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It is possible ++<p align="justify"><font face="serif">It is possible + to model generators and co-routines using streams. Consider the task, + due to Carl Hewitt, of determining if two trees have the same sequence +-of leaves:</font></font></font></p> ++of leaves:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(same-fringe? = +-'(1 (2 3)) '((1 2) 3)) ⇒ #t</font></font></font></p> ++<p align="justify"><font face="monospace">(same-fringe? = ++'(1 (2 3)) '((1 2) 3)) ⇒ #t</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(same-fringe? = +-'(1 2 3) '(1 (3 2))) ⇒ #f</font></font></font></p> ++<p align="justify"><font face="monospace">(same-fringe? = ++'(1 2 3) '(1 (3 2))) ⇒ #f</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The simplest +-solution is to flatten both trees into lists and compare them element-by-element:</font></font></font></p> ++<p align="justify"><font face="serif">The simplest ++solution is to flatten both trees into lists and compare them element-by-element:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (flatten tree) ++<p align="justify"><font face="monospace"><pre> ++(define (flatten tree) + (cond ((null? tree) '()) + ((pair? (car tree)) + (append (flatten (car tree)) + (flatten (cdr tree)))) + (else (cons (car tree) +- (flatten (cdr tree))))))</pre></font></font></font></p> ++ (flatten (cdr tree))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (same-fringe? eql? tree1 tree2) ++<p align="justify"><font face="monospace"><pre> ++(define (same-fringe? eql? tree1 tree2) + (let loop ((t1 (flatten tree1)) + (t2 (flatten tree2))) + (cond ((and (null? t1) (null? t2)) #t) + ((or (null? t1) (null? t2)) #f) + ((not (eql? (car t1) (car t2))) #f) +- (else (loop (cdr t1) (cdr t2))))))</pre></font></font></font></p> ++ (else (loop (cdr t1) (cdr t2))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">That works, ++<p align="justify"><font face="serif">That works, + but requires time to flatten both trees and space to store the flattened + versions; if the trees are large, that can be a lot of time and space, +-and if the fringes differ, much of that time and space is wasted.</font></font></font></p> +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Hewitt used ++and if the fringes differ, much of that time and space is wasted.</font></p> ++<p align="justify"><font face="serif">Hewitt used + a generator to flatten the trees one element at a time, storing only + the current elements of the trees and the machines needed to continue + flattening them, so </font><font face="monospace">same-fringe?</font><font face="serif"> could stop early if the trees differ. + Dorai Sitaram presents both the generator solution and a co-routine +-solution, which both involve tricky calls to </font><font face="monospace">call-with-current-continuation</font><font face="serif"> and careful coding to keep them synchronized.</font></font></font></p> ++solution, which both involve tricky calls to </font><font face="monospace">call-with-current-continuation</font><font face="serif"> and careful coding to keep them synchronized.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">An alternate ++<p align="justify"><font face="serif">An alternate + solution flattens the two trees to streams instead of lists, which accomplishes + the same savings of time and space, and involves code that looks little +-different than the list solution presented above:</font></font></font></p> ++different than the list solution presented above:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (flatten tree) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (flatten tree) + (cond ((null? tree) stream-null) + ((pair? (car tree)) + (stream-append +@@ -1451,9 +1534,10 @@ different than the list solution presented above:</font></font></font></p> + (flatten (cdr tree)))) + (else (stream-cons + (car tree) +- (flatten (cdr tree))))))</pre></font></font></font></p> ++ (flatten (cdr tree))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (same-fringe? eql? tree1 tree2) ++<p align="justify"><font face="monospace"><pre> ++(define (same-fringe? eql? tree1 tree2) + (let loop ((t1 (flatten tree1)) + (t2 (flatten tree2))) + (cond ((and (stream-null? t1) +@@ -1463,128 +1547,146 @@ different than the list solution presented above:</font></font></font></p> + ((not (eql? (stream-car t1) + (stream-car t2))) #f) + (else (loop (stream-cdr t1) +- (stream-cdr t2))))))</pre></font></font></font></p> ++ (stream-cdr t2))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Note that streams, ++<p align="justify"><font face="serif">Note that streams, + a data structure, replace generators or co-routines, which are control +-structures, providing a fine example of how lazy streams enhance modularity.</font></font></font></p> ++structures, providing a fine example of how lazy streams enhance modularity.</font></p> + +-<h2><font face="serif"><font face="serif">A pipeline of procedures</font></font></h2> ++<h3>A pipeline of procedures</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Another way ++<p align="justify"><font face="serif">Another way + in which streams promote modularity is enabling the use of many small + procedures that are easily composed into larger programs, in the style + of unix pipelines, where streams are important because they allow a + large dataset to be processed one item at a time. Bird and Wadler +-provide the example of a text formatter. Their example uses right-folds:</font></font></font></p> ++provide the example of a text formatter. Their example uses right-folds:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-fold-right f base strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-fold-right f base strm) + (if (stream-null? strm) + base + (f (stream-car strm) + (stream-fold-right f base +- (stream-cdr strm)))))</pre></font></font></font></p> ++ (stream-cdr strm)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-fold-right-one f strm) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-fold-right-one f strm) + (stream-match strm + ((x) x) + ((x . xs) +- (f x (stream-fold-right-one f xs)))))</pre></font></font></font></p> ++ (f x (stream-fold-right-one f xs)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Bird and Wadler ++<p align="justify"><font face="serif">Bird and Wadler + define text as a stream of characters, and develop a standard package + for operating on text, which they derive mathematically (this assumes +-the line-separator character is a single </font><font face="monospace">#\newline</font><font face="serif">):</font></font></font></p> ++the line-separator character is a single </font><font face="monospace">#\newline</font><font face="serif">):</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (breakon a) ++<p align="justify"><font face="monospace"><pre> ++(define (breakon a) + (stream-lambda (x xss) + (if (equal? a x) + (stream-append (stream (stream)) xss) + (stream-append + (stream (stream-append + (stream x) (stream-car xss))) +- (stream-cdr xss)))))</pre></font></font></font></p> ++ (stream-cdr xss)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (lines strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (lines strm) + (stream-fold-right + (breakon #\newline) + (stream (stream)) +- strm))</pre></font></font></font></p> ++ strm))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (words strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (words strm) + (stream-filter stream-pair? + (stream-fold-right + (breakon #\space) + (stream (stream)) +- strm)))</pre></font></font></font></p> ++ strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (paras strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (paras strm) + (stream-filter stream-pair? + (stream-fold-right + (breakon stream-null) + (stream (stream)) +- strm)))</pre></font></font></font></p> ++ strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (insert a) ++<p align="justify"><font face="monospace"><pre> ++(define (insert a) + (stream-lambda (xs ys) +- (stream-append xs (stream a) ys)))</pre></font></font></font></p> ++ (stream-append xs (stream a) ys)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define unlines ++<p align="justify"><font face="monospace"><pre> ++(define unlines + (lsec stream-fold-right-one +- (insert #\newline)))</pre></font></font></font></p> ++ (insert #\newline)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define unwords ++<p align="justify"><font face="monospace"><pre> ++(define unwords + (lsec stream-fold-right-one +- (insert #\space)))</pre></font></font></font></p> ++ (insert #\space)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define unparas ++<p align="justify"><font face="monospace"><pre> ++(define unparas + (lsec stream-fold-right-one +- (insert stream-null)))</pre></font></font></font></p> ++ (insert stream-null)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">These versatile ++<p align="justify"><font face="serif">These versatile + procedures can be composed to count words, lines and paragraphs; the </font><font face="monospace">normalize</font><font face="serif"> +-procedure squeezes out multiple spaces and blank lines:</font></font></font></p> ++procedure squeezes out multiple spaces and blank lines:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define countlines +- (compose stream-length lines))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define countlines ++ (compose stream-length lines))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define countwords ++<p align="justify"><font face="monospace"><pre> ++(define countwords + (compose stream-length + stream-concat + (lsec stream-map words) +- lines))</pre></font></font></font></p> ++ lines))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define countparas +- (compose stream-length paras lines))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define countparas ++ (compose stream-length paras lines))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define parse ++<p align="justify"><font face="monospace"><pre> ++(define parse + (compose (lsec stream-map + (lsec stream-map words)) + paras +- lines))</pre></font></font></font></p> ++ lines))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define unparse ++<p align="justify"><font face="monospace"><pre> ++(define unparse + (compose unlines + unparas + (lsec stream-map +- (lsec stream-map unwords))))</pre></font></font></font></p> ++ (lsec stream-map unwords))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define normalize (compose unparse parse))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define normalize (compose unparse parse))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">More useful ++<p align="justify"><font face="serif">More useful + than normalization is text-filling, which packs as many words onto each +-line as will fit.</font></font></font></p> ++line as will fit.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (greedy m ws) ++<p align="justify"><font face="monospace"><pre> ++(define (greedy m ws) + (- (stream-length + (stream-take-while (rsec <= m) + (stream-scan + (lambda (n word) + (+ n (stream-length word) 1)) + -1 +- ws))) 1))</pre></font></font></font></p> ++ ws))) 1))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (fill m ws) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (fill m ws) + (if (stream-null? ws) + stream-null + (let* ((n (greedy m ws)) +@@ -1592,115 +1694,130 @@ line as will fit.</font></font></font></p> + (rstwrds (stream-drop n ws))) + (stream-append + (stream fstline) +- (fill m rstwrds)))))</pre></font></font></font></p> ++ (fill m rstwrds)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define linewords ++<p align="justify"><font face="monospace"><pre> ++(define linewords + (compose stream-concat +- (lsec stream-map words)))</pre></font></font></font></p> ++ (lsec stream-map words)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define textparas ++<p align="justify"><font face="monospace"><pre> ++(define textparas + (compose (lsec stream-map linewords) + paras +- lines))</pre></font></font></font></p> ++ lines))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (filltext m strm) +- (unparse (stream-map (lsec fill m) (textparas strm))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (filltext m strm) ++ (unparse (stream-map (lsec fill m) (textparas strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">To display <i> +-filename</i> in lines of <i>n</i> characters, say:</font></font></font></p> ++<p align="justify"><font face="serif">To display <i> ++filename</i> in lines of <i>n</i> characters, say:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(stream-for-each display +- (filltext </font><font face="serif"><i>n</i></font><font face="monospace"> (file->stream </font><font face="serif"><i>filename</i></font><font face="monospace">)))</font></font></font></pre><p></p> ++<p align="justify"><pre><font face="monospace"> ++(stream-for-each display ++ (filltext </font><font face="serif"><i>n</i></font><font face="monospace"> (file->stream </font><font face="serif"><i>filename</i></font><font face="monospace">)))</font></pre></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Though each ++<p align="justify"><font face="serif">Though each + operator performs only a single task, they can be composed powerfully + and expressively. The alternative is to build a single monolithic + procedure for each task, which would be harder and involve repetitive +-code. Streams ensure procedures are called as needed.</font></font></font></p> ++code. Streams ensure procedures are called as needed.</font></p> + +-<h2><font face="serif"><font face="serif">Persistent data</font></font></h2> ++<h3>Persistent data</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Queues are ++<p align="justify"><font face="serif">Queues are + one of the fundamental data structures of computer science. In + functional languages, queues are commonly implemented using two lists, + with the front half of the queue in one list, where the head of the + queue can be accessed easily, and the rear half of the queue in reverse + order in another list, where new items can easily be added to the end + of a queue. The standard form of such a queue holds that the front +-list can only be null if the rear list is also null: </font></font></font></p> ++list can only be null if the rear list is also null: </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(define queue-null (cons '() '())</font></font></font></p> ++<p align="justify"><font face="monospace">(define queue-null (cons '() '())</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-null? obj) +- (and (pair? obj) (null? (car obj))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (queue-null? obj) ++ (and (pair? obj) (null? (car obj))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-check f r) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-check f r) + (if (null? f) + (cons (reverse r) '()) +- (cons f r)))</pre></font></font></font></p> ++ (cons f r)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-snoc q x) +- (queue-check (car q) (cons x (cdr q))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (queue-snoc q x) ++ (queue-check (car q) (cons x (cdr q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-head q) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-head q) + (if (null? (car q)) + (error "empty queue: head") +- (car (car q))))</pre></font></font></font></p> ++ (car (car q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-tail q) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-tail q) + (if (null? (car q)) + (error "empty-head: tail") +- (queue-check (cdr (car q)) (cdr q))))</pre></font></font></font></p> ++ (queue-check (cdr (car q)) (cdr q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">This queue ++<p align="justify"><font face="serif">This queue + operates in amortized constant time per operation, with two conses per + element, one when it is added to the rear list, and another when the + rear list is reversed to become the front list. </font><font face="monospace">Queue-snoc</font><font face="serif"> and </font><font face="monospace">queue-head</font><font face="serif"> operate in constant time; </font><font face="monospace">queue-tail</font><font face="serif"> +-operates in worst-case linear time when the front list is empty.</font></font></font></p> ++operates in worst-case linear time when the front list is empty.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Chris Okasaki ++<p align="justify"><font face="serif">Chris Okasaki + points out that, if the queue is used persistently, its time-complexity + rises from linear to quadratic since each persistent copy of the queue + requires its own linear-time access. The problem can be fixed + by implementing the front and rear parts of the queue as streams, rather + than lists, and rotating one element from rear to front whenever the +-rear list is larger than the front list: </font></font></font></p> ++rear list is larger than the front list: </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define queue-null +- (cons stream-null stream-null))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define queue-null ++ (cons stream-null stream-null))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-null? x) +- (and (pair? x) (stream-null (car x))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (queue-null? x) ++ (and (pair? x) (stream-null (car x))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-check f r) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-check f r) + (if (< (stream-length r) (stream-length f)) + (cons f r) + (cons (stream-append f (stream-reverse r)) +- stream-null)))</pre></font></font></font></p> ++ stream-null)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-snoc q x) +- (queue-check (car q) (stream-cons x (cdr q))))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (queue-snoc q x) ++ (queue-check (car q) (stream-cons x (cdr q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-head q) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-head q) + (if (stream-null? (car q)) + (error "empty queue: head") +- (stream-car (car q))))</pre></font></font></font></p> ++ (stream-car (car q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (queue-tail q) ++<p align="justify"><font face="monospace"><pre> ++(define (queue-tail q) + (if (stream-null? (car q)) + (error "empty queue: tail") + (queue-check (stream-cdr (car q)) +- (cdr q))))</pre></font></font></font></p> ++ (cdr q))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Memoization ++<p align="justify"><font face="serif">Memoization + solves the persistence problem; once a queue element has moved from + rear to front, it need never be moved again in subsequent traversals + of the queue. Thus, the linear time-complexity to access all elements +-in the queue, persistently, is restored. </font></font></font></p> ++in the queue, persistently, is restored. </font></p> + +-<h2><font face="serif"><font face="serif">Reducing two passes to one</font></font></h2> ++<h3>Reducing two passes to one</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The final example ++<p align="justify"><font face="serif">The final example + is a lazy dictionary, where definitions and uses may occur in any order; + in particular, uses may precede their corresponding definitions. + This is a common problem. Many programming languages allow procedures +@@ -1710,9 +1827,10 @@ to know the address that a linker will subsequently give to variables. + The usual method is to make two passes over the data, collecting the + definitions on the first pass and emitting the uses on the second pass. + But Chris Reade shows how streams allow the dictionary to be built lazily, +-so that only a single pass is needed. Consider a stream of requests:</font></font></font></p> ++so that only a single pass is needed. Consider a stream of requests:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define requests ++<p align="justify"><font face="monospace"><pre> ++(define requests + (stream + '(get 3) + '(put 1 "a") ; use follows definition +@@ -1720,118 +1838,128 @@ so that only a single pass is needed. Consider a stream of requests:</font></fo + '(get 1) + '(get 2) + '(put 2 "b") ; use precedes definition +- '(put 4 "d"))) ; unused definition</pre></font></font></font></p> ++ '(put 4 "d"))) ; unused definition</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">We want a procedure ++<p align="justify"><font face="serif">We want a procedure + that will display </font><font face="monospace">cab</font><font face="serif">, which is the result of </font><font face="monospace">(get 3)</font><font face="serif">, </font><font face="monospace">(get 1)</font><font face="serif">, + and </font><font face="monospace">(get 2)</font><font face="serif">, + in order. We first separate the request stream into </font><font face="monospace">gets</font><font face="serif"> +-and </font><font face="monospace">puts</font><font face="serif">:</font></font></font></p> ++and </font><font face="monospace">puts</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (get? obj) (eq? (car obj) 'get))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define (get? obj) (eq? (car obj) 'get))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (gets strm) +- (stream-map cadr (stream-filter get? strm)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define-stream (gets strm) ++ (stream-map cadr (stream-filter get? strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (puts strm) +- (stream-map cdr (stream-remove get? strm)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(define-stream (puts strm) ++ (stream-map cdr (stream-remove get? strm)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Now, </font><font face="monospace">run-dict</font><font face="serif"> ++<p align="justify"><font face="serif">Now, </font><font face="monospace">run-dict</font><font face="serif"> + inserts each element of the </font><font face="monospace">puts</font><font face="serif"> stream into a lazy dictionary, represented + as a stream of key/value pairs (an association stream), then looks up +-each element of the </font><font face="monospace">gets</font><font face="serif"> stream with </font><font face="monospace">stream-assoc</font><font face="serif">:</font></font></font></p> ++each element of the </font><font face="monospace">gets</font><font face="serif"> stream with </font><font face="monospace">stream-assoc</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (run-dict requests) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (run-dict requests) + (let ((dict (build-dict (puts requests)))) + (stream-map (rsec stream-assoc dict) +- (gets requests))))</pre></font></font></font></p> ++ (gets requests))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-assoc key dict) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-assoc key dict) + (cond ((stream-null? dict) #f) + ((equal? key (car (stream-car dict))) + (stream-car dict)) + (else (stream-assoc key +- (stream-cdr dict)))))</pre></font></font></font></p> ++ (stream-cdr dict)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">Dict</font><font face="serif"> is created in the </font><font face="monospace">let</font><font face="serif">, but nothing is initially added to ++<p align="justify"><font face="monospace">Dict</font><font face="serif"> is created in the </font><font face="monospace">let</font><font face="serif">, but nothing is initially added to + it. Each time </font><font face="monospace">stream-assoc</font><font face="serif"> performs a lookup, enough of </font><font face="monospace">dict</font><font face="serif"> + is built to satisfy the lookup, but no more. We are assuming that + each item is defined once and only once. All that is left is to +-define the procedure that inserts new items into the dictionary, lazily:</font></font></font></p> ++define the procedure that inserts new items into the dictionary, lazily:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (build-dict puts) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (build-dict puts) + (if (stream-null? puts) + stream-null + (stream-cons + (stream-car puts) +- (build-dict (stream-cdr puts)))))</pre></font></font></font></p> ++ (build-dict (stream-cdr puts)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Now we can +-run the requests and print the result:</font></font></font></p> ++<p align="justify"><font face="serif">Now we can ++run the requests and print the result:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-for-each display +- (stream-map cadr (run-dict requests)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++(stream-for-each display ++ (stream-map cadr (run-dict requests)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The </font><font face="monospace">(put 4 "d")</font><font face="serif"> +-definition is never added to the dictionary because it is never needed.</font></font></font></p> ++<p align="justify"><font face="serif">The </font><font face="monospace">(put 4 "d")</font><font face="serif"> ++definition is never added to the dictionary because it is never needed.</font></p> + +-<h2><font face="serif"><font face="serif">Pitfalls</font></font></h2> ++<h3>Pitfalls</h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Programming ++<p align="justify"><font face="serif">Programming + with streams, or any lazy evaluator, can be tricky, even for programmers + experienced in the genre. Programming with streams is even worse + in Scheme than in a purely functional language, because, though the + streams are lazy, the surrounding Scheme expressions in which they are + embedded are eager. The impedance between lazy and eager can occasionally + lead to astonishing results. Thirty-two years ago, William Burge +-warned:</font></font></font></p> ++warned:</font></p> + +-<ul><p align="justify"><font face="serif"><font face="serif"><font face="serif">Some care ++<p align="justify"><font face="serif">Some care + must be taken when a stream is produced to make sure that its elements + are not really a list in disguise, in other words, to make sure that +-the stream elements are not materialized too soon.</font></font></font></p></ul> ++the stream elements are not materialized too soon.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">For example, ++<p align="justify"><font face="serif">For example, + a simple version of </font><font face="monospace">stream-map</font><font face="serif"> that returns a stream built by applying + a unary procedure to the elements of an input stream could be defined +-like this:</font></font></font></p> ++like this:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-map proc strm) ;wrong! ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-map proc strm) ;wrong! + (let loop ((strm strm)) + (if (stream-null? strm) + stream-null + (stream-cons + (proc (stream-car strm)) +- (loop (stream-cdr strm))))))</pre></font></font></font></p> ++ (loop (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">That looks ++<p align="justify"><font face="serif">That looks + right. It properly wraps the procedure in </font><font face="monospace">stream-lambda</font><font face="serif">, and the two legs of the </font><font face="monospace">if</font><font face="serif"> + both return streams, so it type-checks. But it fails because the + named </font><font face="monospace">let</font><font face="serif"> + binds </font><font face="monospace">loop</font><font face="serif"> + to a procedure using normal </font><font face="monospace">lambda</font><font face="serif"> rather than </font><font face="monospace">stream-lambda</font><font face="serif">, so even though the first element + of the result stream is lazy, subsequent elements are eager. </font><font face="monospace">Stream-map</font><font face="serif"> +-can be written using </font><font face="monospace">stream-let</font><font face="serif">:</font></font></font></p> ++can be written using </font><font face="monospace">stream-let</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-map proc strm) ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-map proc strm) + (stream-let loop ((strm strm)) + (if (stream-null? strm) + stream-null + (stream-cons + (proc (stream-car strm)) +- (loop (stream-cdr strm))))))</pre></font></font></font></p> ++ (loop (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Here, </font><font face="monospace">stream-let</font><font face="serif"> ++<p align="justify"><font face="serif">Here, </font><font face="monospace">stream-let</font><font face="serif"> + assures that each element of the result stream is properly delayed, + because each is subject to the </font><font face="monospace">stream-lambda</font><font face="serif"> that is implicit in </font><font face="monospace">stream-let</font><font face="serif">, so the result is truly a stream, +-not a “list in disguise.” Another version of this procedure +-was given previously at the description of </font><font face="monospace">define-stream</font><font face="serif">.</font></font></font></p> ++not a “list in disguise.” Another version of this procedure ++was given previously at the description of </font><font face="monospace">define-stream</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Another common ++<p align="justify"><font face="serif">Another common + problem occurs when a stream-valued procedure requires the next stream +-element in its definition. Consider this definition of </font><font face="monospace">stream-unique</font><font face="serif">:</font></font></font></p> ++element in its definition. Consider this definition of </font><font face="monospace">stream-unique</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define-stream (stream-unique eql? strm) ;wrong! ++<p align="justify"><font face="monospace"><pre> ++(define-stream (stream-unique eql? strm) ;wrong! + (stream-match strm + (() strm) + ((_) strm) +@@ -1841,49 +1969,51 @@ element in its definition. Consider this definition of </font><font face="monos + (stream-cdr strm)) + (stream-cons a + (stream-unique eql? +- (stream-cdr strm)))))))</pre></font></font></font></p> ++ (stream-cdr strm)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The </font><font face="monospace">(a b . _)</font><font face="serif"> ++<p align="justify"><font face="serif">The </font><font face="monospace">(a b . _)</font><font face="serif"> + pattern requires the value of the next stream element after the one + being considered. Thus, to compute the <i>n</i><sup>th</sup> element + of the stream, one must know the <i>n</i>+1<sup>st</sup> element, and + to compute the <i>n</i>+1<sup>st</sup> element, one must know the <i> +-n</i>+2<sup>nd</sup> element, and to compute…. The correct version, +-given above in the description of </font><font face="monospace">stream-drop-while</font><font face="serif">, only needs the current stream element.</font></font></font></p> ++n</i>+2<sup>nd</sup> element, and to compute…. The correct version, ++given above in the description of </font><font face="monospace">stream-drop-while</font><font face="serif">, only needs the current stream element.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">A similar problem ++<p align="justify"><font face="serif">A similar problem + occurs when the stream expression uses the previous element to compute +-the current element:</font></font></font></p> ++the current element:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace">(define (nat n) ++<p align="justify"><font face="monospace"><pre> ++(define (nat n) + (stream-ref + (stream-let loop ((s (stream 0))) + (stream-cons (stream-car s) + (loop (stream (add1 (stream-car s)))))) +- n))</font></font></font></pre><p></p> ++ n))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">This program ++<p align="justify"><font face="serif">This program + traverses the stream of natural numbers, building the stream as it goes. + The definition is correct; </font><font face="monospace">(nat + 15)</font><font face="serif"> evaluates to </font><font face="monospace">15</font><font face="serif">. + But it needlessly uses unbounded space because each stream element holds +-the value of the prior stream element in the binding to </font><font face="monospace">s</font><font face="serif">.</font></font></font></p> ++the value of the prior stream element in the binding to </font><font face="monospace">s</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">When traversing ++<p align="justify"><font face="serif">When traversing + a stream, it is easy to write the expression in such a way that evaluation + requires unbounded space, even when that is not strictly necessary. + During the discussion of SRFI-40, Joe Marshall created this infamous +-procedure:</font></font></font></p> ++procedure:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (times3 n) ++<p align="justify"><font face="monospace"><pre> ++(define (times3 n) + (stream-ref + (stream-filter + (lambda (x) + (zero? (modulo x n))) + (stream-from 0)) +- 3))</pre></font></font></font></p> ++ 3))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(times3 5)</font><font face="serif"> evaluates to </font><font face="monospace">15</font><font face="serif"> and </font><font face="monospace">(times3 ++<p align="justify"><font face="monospace">(times3 5)</font><font face="serif"> evaluates to </font><font face="monospace">15</font><font face="serif"> and </font><font face="monospace">(times3 + #e1e9)</font><font face="serif"> evaluates to three + billion, though it takes a while. In either case, </font><font face="monospace">times3</font><font face="serif"> + should operate in bounded space, since each iteration mutates the promise +@@ -1895,18 +2025,19 @@ the stream, so it holds the head of the stream, which holds the second + element, and so on. In addition to testing the programmer, this + procedure tests the stream primitives (it caught several errors during + development) and also tests the underlying Scheme system (it found a +-bug in one implementation).</font></font></font></p> ++bug in one implementation).</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Laziness is ++<p align="justify"><font face="serif">Laziness is + no defense against an infinite loop; for instance, the expression below + never returns, because the </font><font face="monospace">odd?</font><font face="serif"> predicate never finds an odd stream +-element.</font></font></font></p> ++element.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-null? ++<p align="justify"><font face="monospace"><pre> ++(stream-null? + (stream-filter odd? +- (stream-from 0 2)))</pre></font></font></font></p> ++ (stream-from 0 2)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Ultimately, ++<p align="justify"><font face="serif">Ultimately, + streams are defined as promises, which are implemented as thunks (lambda + with no arguments). Since a stream is a procedure, comparisons + such as </font><font face="monospace">eq?</font><font face="serif">, </font><font face="monospace">eqv?</font><font face="serif"> +@@ -1919,9 +2050,10 @@ s)</font><font face="serif"> is </font><font face="monospace">#t</font><font fac + s stream-null)</font><font face="serif"> is </font><font face="monospace">#f</font><font face="serif">. + To determine if two streams are equal, it is necessary to evaluate the + elements in their common prefixes, reporting </font><font face="monospace">#f</font><font face="serif"> if two elements ever differ and </font><font face="monospace">#t</font><font face="serif"> +-if both streams are exhausted at the same time.</font></font></font></p> ++if both streams are exhausted at the same time.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define (stream-equal? eql? xs ys) ++<p align="justify"><font face="monospace"><pre> ++(define (stream-equal? eql? xs ys) + (cond ((and (stream-null? xs) + (stream-null? ys)) #t) + ((or (stream-null? xs) +@@ -1930,109 +2062,117 @@ if both streams are exhausted at the same time.</font></font></font></p> + (stream-car ys))) #f) + (else (stream-equal? eql? + (stream-cdr xs) +- (stream-cdr ys)))))</pre></font></font></font></p> ++ (stream-cdr ys)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It is generally ++<p align="justify"><font face="serif">It is generally + not a good idea to mix lazy streams with eager side-effects, because + the order in which stream elements are evaluated determines the order + in which the side-effects occur. For a simple example, consider +-this side-effecting version of </font><font face="monospace">strm123</font><font face="serif">:</font></font></font></p> ++this side-effecting version of </font><font face="monospace">strm123</font><font face="serif">:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(define strm123-with-side-effects ++<p align="justify"><font face="monospace"><pre> ++(define strm123-with-side-effects + (stream-cons (begin (display "one") 1) + (stream-cons (begin (display "two") 2) + (stream-cons (begin (display "three") 3) +- stream-null))))</pre></font></font></font></p> ++ stream-null))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The stream ++<p align="justify"><font face="serif">The stream + has elements </font><font face="monospace">1</font><font face="serif"> </font><font face="monospace">2</font><font face="serif"> </font><font face="monospace">3</font><font face="serif">. + But depending on the order in which stream elements are accessed, </font><font face="monospace">"one"</font><font face="serif">, </font><font face="monospace">"two"</font><font face="serif"> +-and </font><font face="monospace">"three"</font><font face="serif"> could be printed in any order.</font></font></font></p> ++and </font><font face="monospace">"three"</font><font face="serif"> could be printed in any order.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Since the performance ++<p align="justify"><font face="serif">Since the performance + of streams can be very poor, normal (eager) lists should be preferred + to streams unless there is some compelling reason to the contrary. +-For instance, computing pythagorean triples with streams</font></font></font></p> ++For instance, computing pythagorean triples with streams</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(stream-ref ++<p align="justify"><font face="monospace"><pre> ++(stream-ref + (stream-of (list a b c) + (n in (stream-from 1)) + (a in (stream-range 1 n)) + (b in (stream-range a n)) + (c is (- n a b)) + (= (+ (* a a) (* b b)) (* c c))) +- 50)</pre></font></font></font></p> ++ 50)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">is about two +-orders of magnitude slower than the equivalent expression using loops.</font></font></font></p> ++<p align="justify"><font face="serif">is about two ++orders of magnitude slower than the equivalent expression using loops.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>(do ((n 1 (+ n 1))) ((> n 228)) ++<p align="justify"><font face="monospace"><pre> ++(do ((n 1 (+ n 1))) ((> n 228)) + (do ((a 1 (+ a 1))) ((> a n)) + (do ((b a (+ b 1))) ((> b n)) + (let ((c (- n a b))) + (if (= (+ (* a a) (* b b)) (* c c)) +- (display (list a b c)))))))</pre></font></font></font></p> ++ (display (list a b c)))))))</pre></font></p> + +-<h1><font face="serif"><font face="serif">Implementation</font></font></h1> ++<h2>Implementation</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Bird and Wadler +-describe streams as either null or a pair with a stream in the tail:</font></font></font></p> ++<p align="justify"><font face="serif">Bird and Wadler ++describe streams as either null or a pair with a stream in the tail:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"> +-α list :: null | α * α list</font></font></font></p> ++<p align="justify"><font face="monospace"> ++α list :: null | α * α list</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">That works ++<p align="justify"><font face="serif">That works + in a purely functional language such as Miranda + or Haskell because the entire language is lazy. In +-an eager language like ML or Scheme, of course, it’s just a normal, +-eager list.</font></font></font></p> ++an eager language like ML or Scheme, of course, it’s just a normal, ++eager list.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Using ML, Wadler, +-Taha and MacQueen give the type of even streams as:</font></font></font></p> ++<p align="justify"><font face="serif">Using ML, Wadler, ++Taha and MacQueen give the type of even streams as:</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre>datatype 'a stream_ ++<p align="justify"><font face="monospace"><pre> ++datatype 'a stream_ + = Nil_ + | Cons_ of 'a * 'a stream + withtype 'a stream +- = 'a stream_ susp;</pre></font></font></font></p> ++ = 'a stream_ susp;</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Their </font><font face="monospace">susp</font><font face="serif"> +-type is similar to Scheme’s </font><font face="monospace">promise</font><font face="serif"> type. Since Scheme conflates ++<p align="justify"><font face="serif">Their </font><font face="monospace">susp</font><font face="serif"> ++type is similar to Scheme’s </font><font face="monospace">promise</font><font face="serif"> type. Since Scheme conflates + the notions of record and type (the only way to create a new type disjoint + from all other types is to create a record), it is necessary to distribute +-the suspension through the two constructors of the stream data type:</font></font></font></p> ++the suspension through the two constructors of the stream data type:</font></p> + +-<p><font face="serif"><font face="serif"><font face="monospace"><pre>α stream ++<p><font face="monospace"><pre> ++α stream + :: (promise stream-null) +- | (promise (α stream-pair))</pre></font></font></font></p> ++ | (promise (α stream-pair))</pre></font></p> + +-<p><font face="serif"><font face="serif"><font face="monospace"><pre>α stream-pair +- :: α × (α stream)</pre></font></font></font></p> ++<p><font face="monospace"><pre> ++α stream-pair ++ :: α × (α stream)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">That type captures ++<p align="justify"><font face="serif">That type captures + the systematic suspension of recursive promises that is the essence +-of “streamness.” But it doesn’t quite work, because Scheme ++of “streamness.” But it doesn’t quite work, because Scheme + is eager rather than lazy, and both the car and the cdr of the stream + are evaluated too early. So the final type of streams delays both +-the car and the cdr of the stream-pair:</font></font></font></p> ++the car and the cdr of the stream-pair:</font></p> + +-<p><font face="serif"><font face="serif"><font face="monospace"><pre>α stream ++<p><font face="monospace"><pre> ++α stream + :: (promise stream-null) +- | (promise (α stream-pair))</pre></font></font></font></p> ++ | (promise (α stream-pair))</pre></font></p> + +-<p><font face="serif"><font face="serif"><font face="monospace"><pre>α stream-pair +- :: (promise α) × (promise (α stream))</pre></font></font></font></p> ++<p><font face="monospace"><pre> ++α stream-pair ++ :: (promise α) × (promise (α stream))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">The two outer ++<p align="justify"><font face="serif">The two outer + promises, in the </font><font face="monospace">stream</font><font face="serif"> type, provide streams without memoization. + The two inner promises, in the </font><font face="monospace">stream-pair</font><font face="serif"> type, add the memoization that is +-characteristic of streams in modern functional languages.</font></font></font></p> ++characteristic of streams in modern functional languages.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Lists provide ++<p align="justify"><font face="serif">Lists provide + seven primitive operations: the two constructors </font><font face="monospace">'()</font><font face="serif"> and </font><font face="monospace">cons</font><font face="serif">, the type predicates </font><font face="monospace">list?</font><font face="serif">, </font><font face="monospace">null?</font><font face="serif"> and </font><font face="monospace">pair?</font><font face="serif">, and the accessors </font><font face="monospace">car</font><font face="serif"> and </font><font face="monospace">cdr</font><font face="serif"> for pairs. All other list operations +-can be derived from those primitives.</font></font></font></p> ++can be derived from those primitives.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">It would seem ++<p align="justify"><font face="serif">It would seem + that the same set of primitives could apply to streams, but in fact + one additional primitive is required. André van Tonder describes + the reason in his discussion of the promise data type. The promises +@@ -2042,44 +2182,44 @@ closure that defines the new promise (so the old promise can be forced + later, if requested). However, in the case of iteration, the old + promise becomes unreachable, so instead of creating a new promise that + binds the old promise within, it is better to mutate the promise; that +-way, no space is wasted by the old promise.</font></font></font></p> ++way, no space is wasted by the old promise.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Van Tonder ++<p align="justify"><font face="serif">Van Tonder + describes this new promise type, and provides a recipe for its use: + all constructors are wrapped with </font><font face="monospace">delay</font><font face="serif">, all accessors are wrapped with </font><font face="monospace">force</font><font face="serif">, + and all function bodies are wrapped with </font><font face="monospace">lazy</font><font face="serif">. Given the seven primitives +-above, the first two parts of van Tonder’s recipe are simple: the ++above, the first two parts of van Tonder’s recipe are simple: the + two constructors </font><font face="monospace">stream-null</font><font face="serif"> and </font><font face="monospace">stream-pair</font><font face="serif"> hide </font><font face="monospace">delay</font><font face="serif">, and the two accessors </font><font face="monospace">stream-car</font><font face="serif"> + and </font><font face="monospace">stream-cdr</font><font face="serif"> + hide </font><font face="monospace">force</font><font face="serif"> + (</font><font face="monospace">stream-null?</font><font face="serif"> + and </font><font face="monospace">stream-pair?</font><font face="serif"> also hide </font><font face="monospace">force</font><font face="serif">, so they can distinguish the two constructors +-of the stream type).</font></font></font></p> ++of the stream type).</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Although the ++<p align="justify"><font face="serif">Although the + new promise type prevents a space leak, it creates a new problem: there +-is no place to hide the </font><font face="monospace">lazy</font><font face="serif"> that is the third part of van Tonder’s ++is no place to hide the </font><font face="monospace">lazy</font><font face="serif"> that is the third part of van Tonder’s + recipe. SRFI-40 solved this problem by exposing it (actually, + it exposed </font><font face="monospace">delay</font><font face="serif">, which was incorrect). But that + violates good software engineering by preventing the stream + data type from being fully abstract. The solution of SRFI-41 is +-to create a new primitive, </font><font face="monospace">stream-lambda</font><font face="serif">, that returns a function that hides </font><font face="monospace">lazy</font><font face="serif">.</font></font></font></p> ++to create a new primitive, </font><font face="monospace">stream-lambda</font><font face="serif">, that returns a function that hides </font><font face="monospace">lazy</font><font face="serif">.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Besides hiding </font><font face="monospace">lazy</font><font face="serif"> ++<p align="justify"><font face="serif">Besides hiding </font><font face="monospace">lazy</font><font face="serif"> + and making the types work out correctly, </font><font face="monospace">stream-lambda</font><font face="serif"> is obvious and easy-to-use for competent + Scheme programmers, especially when augmented with the syntactic sugar + of </font><font face="monospace">define-stream</font><font face="serif"> and named </font><font face="monospace">stream-let</font><font face="serif">. The alternative of exposing </font><font face="monospace">stream-lazy</font><font face="serif"> +-would be less clear and harder to use.</font></font></font></p> ++would be less clear and harder to use.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">One of the ++<p align="justify"><font face="serif">One of the + hardest tasks when writing any program library is to decide what to + include and, more importantly, what to exclude. One important + guideline is minimalism, since once an operator enters a library it + must remain forever: <i>Il semble que la perfection soit atteinte non +-quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien +-à retrancher</i>.</font></font></font></p> ++quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien ++à retrancher</i>.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Since streams ++<p align="justify"><font face="serif">Since streams + are substantially slower than lists (the stream primitives require numerous + type conversions, and list operations in most Scheme implementations + are heavily optimized), most programmers will use streams only when +@@ -2088,36 +2228,43 @@ or when there is some clear advantage of laziness (such as reducing + the number of passes though a large data set). Thus, the library + is biased toward functions that work with infinite streams left-to-right. + In particular, there is no right-fold; if you need to materialize an entire stream, +-it’s best to use a list.</font></font></font></p> ++it’s best to use a list.</font></p> + +-<h2><font face="serif"><font face="serif">Implementation of <font face="monospace">(streams primitive)</font></font></font></h2> ++<h3>Implementation of <font face="monospace">(streams primitive)</font></h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(library (streams primitive)</font></font></font></p> ++<p align="justify"><font face="monospace">(library (streams primitive)</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (export stream-null stream-cons stream? stream-null? stream-pair? +- stream-car stream-cdr stream-lambda)</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (export stream-null stream-cons stream? stream-null? stream-pair? ++ stream-car stream-cdr stream-lambda)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (import (rnrs) (rnrs mutable-pairs))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (import (rnrs) (rnrs mutable-pairs))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-record-type (stream-type make-stream stream?) +- (fields (mutable box stream-promise stream-promise!)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (define-record-type (stream-type make-stream stream?) ++ (fields (mutable box stream-promise stream-promise!)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-lazy ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-lazy + (syntax-rules () + ((stream-lazy expr) + (make-stream +- (cons 'lazy (lambda () expr))))))</pre></font></font></font></p> ++ (cons 'lazy (lambda () expr))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-eager expr) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-eager expr) + (make-stream +- (cons 'eager expr)))</font></font></font></pre><p></p> ++ (cons 'eager expr)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-delay ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-delay + (syntax-rules () + ((stream-delay expr) +- (stream-lazy (stream-eager expr)))))</pre></font></font></font></p> ++ (stream-lazy (stream-eager expr)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-force promise) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-force promise) + (let ((content (stream-promise promise))) + (case (car content) + ((eager) (cdr content)) +@@ -2127,61 +2274,73 @@ it’s best to use a list.</font></font></font></p> + (begin (set-car! content (car (stream-promise promise*))) + (set-cdr! content (cdr (stream-promise promise*))) + (stream-promise! promise* content))) +- (stream-force promise))))))</pre></font></font></font></p> ++ (stream-force promise))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define stream-null (stream-delay (cons 'stream 'null)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (define stream-null (stream-delay (cons 'stream 'null)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-record-type (stream-pare-type make-stream-pare stream-pare?) +- (fields (immutable kar stream-kar) (immutable kdr stream-kdr)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (define-record-type (stream-pare-type make-stream-pare stream-pare?) ++ (fields (immutable kar stream-kar) (immutable kdr stream-kdr)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-pair? obj) +- (and (stream? obj) (stream-pare? (stream-force obj))))</font></font></font></pre><p></p> ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-pair? obj) ++ (and (stream? obj) (stream-pare? (stream-force obj))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-null? obj) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-null? obj) + (and (stream? obj) + (eqv? (stream-force obj) +- (stream-force stream-null))))</pre></font></font></font></p> ++ (stream-force stream-null))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-cons ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-cons + (syntax-rules () + ((stream-cons obj strm) +- (stream-eager (make-stream-pare (stream-delay obj) (stream-lazy strm))))))</pre></font></font></font></p> ++ (stream-eager (make-stream-pare (stream-delay obj) (stream-lazy strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-car strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-car strm) + (cond ((not (stream? strm)) (error 'stream-car "non-stream")) + ((stream-null? strm) (error 'stream-car "null stream")) +- (else (stream-force (stream-kar (stream-force strm))))))</pre></font></font></font></p> ++ (else (stream-force (stream-kar (stream-force strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-cdr strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-cdr strm) + (cond ((not (stream? strm)) (error 'stream-cdr "non-stream")) + ((stream-null? strm) (error 'stream-cdr "null stream")) +- (else (stream-kdr (stream-force strm)))))</pre></font></font></font></p> ++ (else (stream-kdr (stream-force strm)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-lambda ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-lambda + (syntax-rules () + ((stream-lambda formals body0 body1 ...) +- (lambda formals (stream-lazy (let () body0 body1 ...)))))))</pre></font></font></font></p> ++ (lambda formals (stream-lazy (let () body0 body1 ...)))))))</pre></font></p> + +-<h2><font face="serif"><font face="serif">Implementation of <font face="monospace">(streams derived)</font></font></font></h2> ++<h3>Implementation of <font face="monospace">(streams derived)</font></h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(library (streams derived)</font></font></font></p> ++<p align="justify"><font face="monospace">(library (streams derived)</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (export stream-null stream-cons stream? stream-null? stream-pair? stream-car ++<p align="justify"><font face="monospace"><pre> ++ (export stream-null stream-cons stream? stream-null? stream-pair? stream-car + stream-cdr stream-lambda define-stream list->stream port->stream stream + stream->list stream-append stream-concat stream-constant stream-drop + stream-drop-while stream-filter stream-fold stream-for-each stream-from + stream-iterate stream-length stream-let stream-map stream-match _ + stream-of stream-range stream-ref stream-reverse stream-scan stream-take +- stream-take-while stream-unfold stream-unfolds stream-zip)</pre></font></font></font></p> ++ stream-take-while stream-unfold stream-unfolds stream-zip)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (import (rnrs) (streams primitive))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (import (rnrs) (streams primitive))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax define-stream ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax define-stream + (syntax-rules () + ((define-stream (name . formal) body0 body1 ...) +- (define name (stream-lambda formal body0 body1 ...)))))</pre></font></font></font></p> ++ (define name (stream-lambda formal body0 body1 ...)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (list->stream objs) ++<p align="justify"><font face="monospace"><pre> ++ (define (list->stream objs) + (define list->stream + (stream-lambda (objs) + (if (null? objs) +@@ -2189,9 +2348,10 @@ it’s best to use a list.</font></font></font></p> + (stream-cons (car objs) (list->stream (cdr objs)))))) + (if (not (list? objs)) + (error 'list->stream "non-list argument") +- (list->stream objs)))</pre></font></font></font></p> ++ (list->stream objs)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (port->stream . port) ++<p align="justify"><font face="monospace"><pre> ++ (define (port->stream . port) + (define port->stream + (stream-lambda (p) + (let ((c (read-char p))) +@@ -2201,14 +2361,16 @@ it’s best to use a list.</font></font></font></p> + (let ((p (if (null? port) (current-input-port) (car port)))) + (if (not (input-port? p)) + (error 'port->stream "non-input-port argument") +- (port->stream p))))</font></font></font></pre><p></p> ++ (port->stream p))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream + (syntax-rules () + ((stream) stream-null) +- ((stream x y ...) (stream-cons x (stream y ...)))))</pre></font></font></font></p> ++ ((stream x y ...) (stream-cons x (stream y ...)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream->list . args) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream->list . args) + (let ((n (if (= 1 (length args)) #f (car args))) + (strm (if (= 1 (length args)) (car args) (cadr args)))) + (cond ((not (stream? strm)) (error 'stream->list "non-stream argument")) +@@ -2217,9 +2379,10 @@ it’s best to use a list.</font></font></font></p> + (else (let loop ((n (if n n -1)) (strm strm)) + (if (or (zero? n) (stream-null? strm)) + '() +- (cons (stream-car strm) (loop (- n 1) (stream-cdr strm)))))))))</font></font></font></pre><p></p> ++ (cons (stream-car strm) (loop (- n 1) (stream-cdr strm)))))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-append . strms) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-append . strms) + (define stream-append + (stream-lambda (strms) + (cond ((null? (cdr strms)) (car strms)) +@@ -2229,9 +2392,10 @@ it’s best to use a list.</font></font></font></p> + (cond ((null? strms) stream-null) + ((exists (lambda (x) (not (stream? x))) strms) + (error 'stream-append "non-stream argument")) +- (else (stream-append strms))))</pre></font></font></font></p> +-<font face="serif"><font face="serif"> +-</font></font><p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-concat strms) ++ (else (stream-append strms))))</pre></font></p> ++ ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-concat strms) + (define stream-concat + (stream-lambda (strms) + (cond ((stream-null? strms) stream-null) +@@ -2245,16 +2409,18 @@ it’s best to use a list.</font></font></font></p> + (stream-cons (stream-cdr (stream-car strms)) (stream-cdr strms)))))))) + (if (not (stream? strms)) + (error 'stream-concat "non-stream argument") +- (stream-concat strms)))</font></font></font></pre><p></p> ++ (stream-concat strms)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define stream-constant ++<p align="justify"><font face="monospace"><pre> ++ (define stream-constant + (stream-lambda objs + (cond ((null? objs) stream-null) + ((null? (cdr objs)) (stream-cons (car objs) (stream-constant (car objs)))) + (else (stream-cons (car objs) +- (apply stream-constant (append (cdr objs) (list (car objs)))))))))</pre></font></font></font></p> ++ (apply stream-constant (append (cdr objs) (list (car objs)))))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-drop n strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-drop n strm) + (define stream-drop + (stream-lambda (n strm) + (if (or (zero? n) (stream-null? strm)) +@@ -2263,9 +2429,10 @@ it’s best to use a list.</font></font></font></p> + (cond ((not (integer? n)) (error 'stream-drop "non-integer argument")) + ((negative? n) (error 'stream-drop "negative argument")) + ((not (stream? strm)) (error 'stream-drop "non-stream argument")) +- (else (stream-drop n strm))))</pre></font></font></font></p> ++ (else (stream-drop n strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-drop-while pred? strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-drop-while pred? strm) + (define stream-drop-while + (stream-lambda (strm) + (if (and (stream-pair? strm) (pred? (stream-car strm))) +@@ -2273,9 +2440,10 @@ it’s best to use a list.</font></font></font></p> + strm))) + (cond ((not (procedure? pred?)) (error 'stream-drop-while "non-procedural argument")) + ((not (stream? strm)) (error 'stream-drop-while "non-stream argument")) +- (else (stream-drop-while strm))))</font></font></font></pre><p></p> ++ (else (stream-drop-while strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-filter pred? strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-filter pred? strm) + (define stream-filter + (stream-lambda (strm) + (cond ((stream-null? strm) stream-null) +@@ -2284,17 +2452,19 @@ it’s best to use a list.</font></font></font></p> + (else (stream-filter (stream-cdr strm)))))) + (cond ((not (procedure? pred?)) (error 'stream-filter "non-procedural argument")) + ((not (stream? strm)) (error 'stream-filter "non-stream argument")) +- (else (stream-filter strm))))</pre></font></font></font></p> ++ (else (stream-filter strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-fold proc base strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-fold proc base strm) + (cond ((not (procedure? proc)) (error 'stream-fold "non-procedural argument")) + ((not (stream? strm)) (error 'stream-fold "non-stream argument")) + (else (let loop ((base base) (strm strm)) + (if (stream-null? strm) + base +- (loop (proc base (stream-car strm)) (stream-cdr strm)))))))</pre></font></font></font></p> ++ (loop (proc base (stream-car strm)) (stream-cdr strm)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-for-each proc . strms) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-for-each proc . strms) + (define (stream-for-each strms) + (if (not (exists stream-null? strms)) + (begin (apply proc (map stream-car strms)) +@@ -2303,39 +2473,44 @@ it’s best to use a list.</font></font></font></p> + ((null? strms) (error 'stream-for-each "no stream arguments")) + ((exists (lambda (x) (not (stream? x))) strms) + (error 'stream-for-each "non-stream argument")) +- (else (stream-for-each strms))))</font></font></font></pre><p></p> ++ (else (stream-for-each strms))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-from first . step) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-from first . step) + (define stream-from + (stream-lambda (first delta) + (stream-cons first (stream-from (+ first delta) delta)))) + (let ((delta (if (null? step) 1 (car step)))) + (cond ((not (number? first)) (error 'stream-from "non-numeric starting number")) + ((not (number? delta)) (error 'stream-from "non-numeric step size")) +- (else (stream-from first delta)))))</pre></font></font></font></p> ++ (else (stream-from first delta)))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-iterate proc base) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-iterate proc base) + (define stream-iterate + (stream-lambda (base) + (stream-cons base (stream-iterate (proc base))))) + (if (not (procedure? proc)) + (error 'stream-iterate "non-procedural argument") +- (stream-iterate base)))</pre></font></font></font></p> ++ (stream-iterate base)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-length strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-length strm) + (if (not (stream? strm)) + (error 'stream-length "non-stream argument") + (let loop ((len 0) (strm strm)) + (if (stream-null? strm) + len +- (loop (+ len 1) (stream-cdr strm))))))</font></font></font></pre><p></p> ++ (loop (+ len 1) (stream-cdr strm))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-let ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-let + (syntax-rules () + ((stream-let tag ((name val) ...) body1 body2 ...) +- ((letrec ((tag (stream-lambda (name ...) body1 body2 ...))) tag) val ...))))</pre></font></font></font></p> ++ ((letrec ((tag (stream-lambda (name ...) body1 body2 ...))) tag) val ...))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-map proc . strms) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-map proc . strms) + (define stream-map + (stream-lambda (strms) + (if (exists stream-null? strms) +@@ -2346,25 +2521,28 @@ it’s best to use a list.</font></font></font></p> + ((null? strms) (error 'stream-map "no stream arguments")) + ((exists (lambda (x) (not (stream? x))) strms) + (error 'stream-map "non-stream argument")) +- (else (stream-map strms))))</pre></font></font></font></p> +-<font face="serif"><font face="serif"> +-</font></font><p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define-syntax stream-match ++ (else (stream-map strms))))</pre></font></p> ++ ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-match + (syntax-rules () + ((stream-match strm-expr clause ...) + (let ((strm strm-expr)) + (cond + ((not (stream? strm)) (error 'stream-match "non-stream argument")) + ((stream-match-test strm clause) => car) ... +- (else (error 'stream-match "pattern failure")))))))</font></font></font></pre><p></p> +-<font face="serif"><font face="serif"> +-</font></font><p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-match-test ++ (else (error 'stream-match "pattern failure")))))))</pre></font></p> ++ ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-match-test + (syntax-rules () + ((stream-match-test strm (pattern fender expr)) + (stream-match-pattern strm pattern () (and fender (list expr)))) + ((stream-match-test strm (pattern expr)) +- (stream-match-pattern strm pattern () (list expr)))))</pre></font></font></font></p> +-<font face="serif"><font face="serif"> +-</font></font><p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define-syntax stream-match-pattern ++ (stream-match-pattern strm pattern () (list expr)))))</pre></font></p> ++ ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-match-pattern + (lambda (x) + (define (wildcard? x) + (and (identifier? x) +@@ -2385,14 +2563,16 @@ it’s best to use a list.</font></font></font></p> + (wildcard? #'w?) + (syntax (let (binding ...) body))) + ((stream-match-pattern strm var (binding ...) body) +- (syntax (let ((var strm) binding ...) body))))))</font></font></font></pre><p></p> +-<font face="serif"><font face="serif"> +-</font></font><p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-of ++ (syntax (let ((var strm) binding ...) body))))))</pre></font></p> ++ ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-of + (syntax-rules () + ((_ expr rest ...) +- (stream-of-aux expr stream-null rest ...))))</pre></font></font></font></p> ++ (stream-of-aux expr stream-null rest ...))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define-syntax stream-of-aux ++<p align="justify"><font face="monospace"><pre> ++ (define-syntax stream-of-aux + (syntax-rules (in is) + ((stream-of-aux expr base) + (stream-cons expr base)) +@@ -2405,9 +2585,10 @@ it’s best to use a list.</font></font></font></p> + ((stream-of-aux expr base (var is exp) rest ...) + (let ((var exp)) (stream-of-aux expr base rest ...))) + ((stream-of-aux expr base pred? rest ...) +- (if pred? (stream-of-aux expr base rest ...) base))))</pre></font></font></font></p> ++ (if pred? (stream-of-aux expr base rest ...) base))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-range first past . step) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-range first past . step) + (define stream-range + (stream-lambda (first past delta lt?) + (if (lt? first past) +@@ -2419,18 +2600,20 @@ it’s best to use a list.</font></font></font></p> + (if (not (number? delta)) + (error 'stream-range "non-numeric step size") + (let ((lt? (if (< 0 delta) < >))) +- (stream-range first past delta lt?)))))))</font></font></font></pre><p></p> ++ (stream-range first past delta lt?)))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-ref strm n) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-ref strm n) + (cond ((not (stream? strm)) (error 'stream-ref "non-stream argument")) + ((not (integer? n)) (error 'stream-ref "non-integer argument")) + ((negative? n) (error 'stream-ref "negative argument")) + (else (let loop ((strm strm) (n n)) + (cond ((stream-null? strm) (error 'stream-ref "beyond end of stream")) + ((zero? n) (stream-car strm)) +- (else (loop (stream-cdr strm) (- n 1))))))))</pre></font></font></font></p> ++ (else (loop (stream-cdr strm) (- n 1))))))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-reverse strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-reverse strm) + (define stream-reverse + (stream-lambda (strm rev) + (if (stream-null? strm) +@@ -2438,9 +2621,10 @@ it’s best to use a list.</font></font></font></p> + (stream-reverse (stream-cdr strm) (stream-cons (stream-car strm) rev))))) + (if (not (stream? strm)) + (error 'stream-reverse "non-stream argument") +- (stream-reverse strm stream-null)))</font></font></font></pre><p></p> ++ (stream-reverse strm stream-null)))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-scan proc base strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-scan proc base strm) + (define stream-scan + (stream-lambda (base strm) + (if (stream-null? strm) +@@ -2448,9 +2632,10 @@ it’s best to use a list.</font></font></font></p> + (stream-cons base (stream-scan (proc base (stream-car strm)) (stream-cdr strm)))))) + (cond ((not (procedure? proc)) (error 'stream-scan "non-procedural argument")) + ((not (stream? strm)) (error 'stream-scan "non-stream argument")) +- (else (stream-scan base strm))))</pre></font></font></font></p> ++ (else (stream-scan base strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-take n strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-take n strm) + (define stream-take + (stream-lambda (n strm) + (if (or (stream-null? strm) (zero? n)) +@@ -2459,9 +2644,10 @@ it’s best to use a list.</font></font></font></p> + (cond ((not (stream? strm)) (error 'stream-take "non-stream argument")) + ((not (integer? n)) (error 'stream-take "non-integer argument")) + ((negative? n) (error 'stream-take "negative argument")) +- (else (stream-take n strm))))</pre></font></font></font></p> ++ (else (stream-take n strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-take-while pred? strm) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-take-while pred? strm) + (define stream-take-while + (stream-lambda (strm) + (cond ((stream-null? strm) stream-null) +@@ -2470,9 +2656,10 @@ it’s best to use a list.</font></font></font></p> + (else stream-null)))) + (cond ((not (stream? strm)) (error 'stream-take-while "non-stream argument")) + ((not (procedure? pred?)) (error 'stream-take-while "non-procedural argument")) +- (else (stream-take-while strm))))</pre></font></font></font></p> ++ (else (stream-take-while strm))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (define (stream-unfold mapper pred? generator base) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-unfold mapper pred? generator base) + (define stream-unfold + (stream-lambda (base) + (if (pred? base) +@@ -2481,9 +2668,10 @@ it’s best to use a list.</font></font></font></p> + (cond ((not (procedure? mapper)) (error 'stream-unfold "non-procedural mapper")) + ((not (procedure? pred?)) (error 'stream-unfold "non-procedural pred?")) + ((not (procedure? generator)) (error 'stream-unfold "non-procedural generator")) +- (else (stream-unfold base))))</pre></font></font></font></p> ++ (else (stream-unfold base))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-unfolds gen seed) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-unfolds gen seed) + (define (len-values gen seed) + (call-with-values + (lambda () (gen seed)) +@@ -2512,9 +2700,10 @@ it’s best to use a list.</font></font></font></p> + (loop (- i 1) (cons (result-stream->output-stream result-stream i) outputs))))) + (if (not (procedure? gen)) + (error 'stream-unfolds "non-procedural argument") +- (result-stream->output-streams (unfold-result-stream gen seed))))</font></font></font></pre><p></p> ++ (result-stream->output-streams (unfold-result-stream gen seed))))</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"></font></font></font></p><pre><font face="serif"><font face="serif"><font face="monospace"> (define (stream-zip . strms) ++<p align="justify"><font face="monospace"><pre> ++ (define (stream-zip . strms) + (define stream-zip + (stream-lambda (strms) + (if (exists stream-null? strms) +@@ -2523,190 +2712,193 @@ it’s best to use a list.</font></font></font></p> + (cond ((null? strms) (error 'stream-zip "no stream arguments")) + ((exists (lambda (x) (not (stream? x))) strms) + (error 'stream-zip "non-stream argument")) +- (else (stream-zip strms)))))</font></font></font></pre><p></p> ++ (else (stream-zip strms)))))</pre></font></p> + +-<h2><font face="serif"><font face="serif">Implementation of <font face="monospace">(streams)</font></font></font></h2> ++<h3>Implementation of <font face="monospace">(streams)</font></h3> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace">(library (streams)</font></font></font></p> ++<p align="justify"><font face="monospace">(library (streams)</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (export stream-null stream-cons stream? stream-null? stream-pair? stream-car ++<p align="justify"><font face="monospace"><pre> ++ (export stream-null stream-cons stream? stream-null? stream-pair? stream-car + stream-cdr stream-lambda define-stream list->stream port->stream stream + stream->list stream-append stream-concat stream-constant stream-drop + stream-drop-while stream-filter stream-fold stream-for-each stream-from + stream-iterate stream-length stream-let stream-map stream-match _ + stream-of stream-range stream-ref stream-reverse stream-scan stream-take +- stream-take-while stream-unfold stream-unfolds stream-zip)</pre></font></font></font></p> ++ stream-take-while stream-unfold stream-unfolds stream-zip)</pre></font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="monospace"><pre> (import (streams primitive) (streams derived)))</pre></font></font></font></p> ++<p align="justify"><font face="monospace"><pre> ++ (import (streams primitive) (streams derived)))</pre></font></p> + +-<h1><font face="serif"><font face="serif">Acknowledgements</font></font></h1> ++<h2>Acknowledgements</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Jos Koot sharpened ++<p align="justify"><font face="serif">Jos Koot sharpened + my thinking during many e-mail discussions, suggested several discussion + points in the text, and contributed the final version of </font><font face="monospace">stream-match</font><font face="serif">. +-Michael Sperber and Abdulaziz Ghuloum gave advice on R6RS.</font></font></font></p> ++Michael Sperber and Abdulaziz Ghuloum gave advice on R6RS.</font></p> + +-<h1><font face="serif"><font face="serif">References</font></font></h1> ++<h2>References</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Harold Abelson ++<p align="justify"><font face="serif">Harold Abelson + and Gerald Jay Sussman with Julie Sussman. <i>Structure and Interpretation + of Computer Programs</i>. MIT Press, Cambridge, Massachusetts. + Second edition, 1996. </font><font face="monospace"><a href="http://mitpress.mit.edu/sicp" target="_blank">mitpress.mit.edu/sicp</a></font><font face="serif">. The classic text on computer +-science. Section 3.5 includes extensive discussion of odd streams.</font></font></font></p> ++science. Section 3.5 includes extensive discussion of odd streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Anne L. Bewig. +-“Golden Ratio” (personal communication). Homework for the ++<p align="justify"><font face="serif">Anne L. Bewig. ++“Golden Ratio” (personal communication). Homework for the + high school course <i>Calculus</i>. Teaching my daughter how to + calculate the 200<sup>th</sup> element of a continued fraction was a +-moment of sheer joy in the development of the stream libraries.</font></font></font></p> ++moment of sheer joy in the development of the stream libraries.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Philip L. Bewig. <i> ++<p align="justify"><font face="serif">Philip L. Bewig. <i> + Scheme Request for Implementation 40: +-A Library of Streams</i>. August, 2004. </font><font face="monospace"><a href="http://srfi.schemers.org/srfi-40" target="_blank">srfi.schemers.org/srfi-40</a></font><font face="serif">. Describes an implementation ++A Library of Streams</i>. August, 2004. </font><font face="monospace"><a href="../srfi-40.html" target="_blank">srfi.schemers.org/srfi-40</a></font><font face="serif">. Describes an implementation + of the </font><font face="monospace">stream</font><font face="serif"> +-data type. </font></font></font></p> ++data type. </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Richard Bird ++<p align="justify"><font face="serif">Richard Bird + and Philip Wadler. <i>Introduction to Functional Programming</i>. + Prentice Hall, 1988. The classic text on functional programming. +-Even streams are discussed in the context of purely functional programming.</font></font></font></p> ++Even streams are discussed in the context of purely functional programming.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">William H. ++<p align="justify"><font face="serif">William H. + Burge. <i>Recursive Programming Techniques</i>. Addison-Wesley, + 1975. An early text on functional programming, and still one of + the best, though the terminology is dated. Discusses even streams +-in Section 3.10.</font></font></font></p> ++in Section 3.10.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Jeremy Gibbons, +-David Lester and Richard Bird, “Functional Pearl: Enumerating the +-Rationals,” under consideration for publication in <i>Journal of Functional +-Programming</i>. </font><font face="monospace"><a href="http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/rationals.pdf" target="_blank">http://web.comlab.ox.ac.uk<wbr>/oucl/work/jeremy.gibbons<wbr>/publications/rationals.pdf</a></font><font face="serif">. Discusses a series of expressions +-that enumerate the rational numbers without duplicates.</font></font></font></p> ++<p align="justify"><font face="serif">Jeremy Gibbons, ++David Lester and Richard Bird, “Functional Pearl: Enumerating the ++Rationals,” under consideration for publication in <i>Journal of Functional ++Programming</i>. </font><font face="monospace"><a href="http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/rationals.pdf" target="_blank">http://web.comlab.ox.ac.uk<wbr />/oucl/work/jeremy.gibbons<wbr />/publications/rationals.pdf</a></font><font face="serif">. Discusses a series of expressions ++that enumerate the rational numbers without duplicates.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Carl Hewitt. +-“Viewing control structures as patterns of passing messages,” in <i> ++<p align="justify"><font face="serif">Carl Hewitt. ++“Viewing control structures as patterns of passing messages,” in <i> + Journal of Artificial Intelligence</i>, Volume 8, Number 3 (June, 1977), + pp 323-364. Also published as Artificial Intelligence Memo 410 +-by the Massachusetts Institute of Technology, </font><font face="monospace"><a href="ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-410.pdf" target="_blank">ftp://publications.ai.mit.edu<wbr>/ai-publications/pdf/AIM-410<wbr>.pdf</a></font><font face="serif">. Describes the Actor message-passing +-system; one of the examples used is the </font><font face="monospace">same-fringe?</font><font face="serif"> problem.</font></font></font></p> ++by the Massachusetts Institute of Technology, </font><font face="monospace"><a href="ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-410.pdf" target="_blank">ftp://publications.ai.mit.edu<wbr />/ai-publications/pdf/AIM-410<wbr />.pdf</a></font><font face="serif">. Describes the Actor message-passing ++system; one of the examples used is the </font><font face="monospace">same-fringe?</font><font face="serif"> problem.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Peter J. Landin. +-“A correspondence between ALGOL 60 and Church’s lambda-notation: +-Part I,” <i>Communications of the ACM</i>, Volume 8, Number +-2, February 1965., pages 89–101. The seminal description of +-streams.</font></font></font></p> ++<p align="justify"><font face="serif">Peter J. Landin. ++“A correspondence between ALGOL 60 and Church’s lambda-notation: ++Part I,” <i>Communications of the ACM</i>, Volume 8, Number ++2, February 1965., pages 89–101. The seminal description of ++streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Joe Marshall. +-“Stream problem redux”, from <i>Usenet +-comp.lang.scheme</i>, June 28, 2002. </font><font face="monospace"><a href="http://groups.google.com/group/comp.lang.scheme/msg/db4b4a1f33e3eea8" target="_blank">groups.google.com/group/comp<wbr>.lang.scheme/msg/db4b4a1f33e3ee<wbr>a8</a></font><font face="serif">. The original post on </font><font face="monospace">comp.lang.scheme</font><font face="serif"> +-that describes the </font><font face="monospace">times3</font><font face="serif"> problem.</font></font></font></p> ++<p align="justify"><font face="serif">Joe Marshall. ++“Stream problem redux”, from <i>Usenet ++comp.lang.scheme</i>, June 28, 2002. </font><font face="monospace"><a href="http://groups.google.com/group/comp.lang.scheme/msg/db4b4a1f33e3eea8" target="_blank">groups.google.com/group/comp<wbr />.lang.scheme/msg/db4b4a1f33e3ee<wbr />a8</a></font><font face="serif">. The original post on </font><font face="monospace">comp.lang.scheme</font><font face="serif"> ++that describes the </font><font face="monospace">times3</font><font face="serif"> problem.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Chris Okasaki. <i> ++<p align="justify"><font face="serif">Chris Okasaki. <i> + Purely Functional Data Structures</i>. Cambridge University Press, +-2003. Revised version of Okasaki’s thesis <i>Purely Functional +-Data Structures</i>, Carnegie-Mellon University, 1996, </font><font face="monospace"><a href="http://www.cs.cmu.edu/%7Erwh/theses/okasaki.pdf" target="_blank">www.cs.cmu.edu/~rwh/theses<wbr>/okasaki.pdf</a></font><font face="serif">. Provides a strong defense of ++2003. Revised version of Okasaki’s thesis <i>Purely Functional ++Data Structures</i>, Carnegie-Mellon University, 1996, </font><font face="monospace"><a href="http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf" target="_blank">www.cs.cmu.edu/~rwh/theses<wbr />/okasaki.pdf</a></font><font face="serif">. Provides a strong defense of + laziness, and describes several data structures that exploit laziness, +-including streams and queues.</font></font></font></p> ++including streams and queues.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Stephen K. +-Park and Keith W. Miller. “Random number generators: good ones +-are hard to find,” <i>Communications of the ACM</i>, Volume 31, Issue +-10 (October 1988), pages 1192–1201. Describes a minimal standard +-random number generator. </font></font></font></p> ++<p align="justify"><font face="serif">Stephen K. ++Park and Keith W. Miller. “Random number generators: good ones ++are hard to find,” <i>Communications of the ACM</i>, Volume 31, Issue ++10 (October 1988), pages 1192–1201. Describes a minimal standard ++random number generator. </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Simon Peyton-Jones, ++<p align="justify"><font face="serif">Simon Peyton-Jones, + et al, editors. <i>Haskell 98: Haskell 98 Language and Libraries: + The Revised Report</i>. December 2002. </font><font face="monospace"><a href="http://www.haskell.org/onlinereport" target="_blank">www.haskell.org/onlinereport</a></font><font face="serif">. Haskell is the prototypical + purely functional language, and includes even streams, which it calls +-lists, as its fundamental structured data type.</font></font></font></p> ++lists, as its fundamental structured data type.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Chris Reade. <i> ++<p align="justify"><font face="serif">Chris Reade. <i> + Elements of Functional Programming</i>. Addison-Wesley, April +-1989. A textbook on functional programming.</font></font></font></p> ++1989. A textbook on functional programming.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Antoine de +-Saint-Exupéry. Chapter III “L’Avion” of <i>Terre des Hommes</i>. +-1939. “Perfection is achieved, not when there is nothing more +-to add, but when there is nothing left to take away.”</font></font></font></p> ++<p align="justify"><font face="serif">Antoine de ++Saint-Exupéry. Chapter III “L’Avion” of <i>Terre des Hommes</i>. ++1939. “Perfection is achieved, not when there is nothing more ++to add, but when there is nothing left to take away.”</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Dorai Sitaram. <i> +-Teach Yourself Scheme in Fixnum Days</i>. </font><font face="monospace"><a href="http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme.html" target="_blank">www.ccs.neu.edu/home/dorai/t-y<wbr>-scheme/t-y-scheme.html</a></font><font face="serif">. A useful introduction to Scheme; +-includes generator and co-routine solutions to the </font><font face="monospace">same-fringe?</font><font face="serif"> problem.</font></font></font></p> ++<p align="justify"><font face="serif">Dorai Sitaram. <i> ++Teach Yourself Scheme in Fixnum Days</i>. </font><font face="monospace"><a href="http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme.html" target="_blank">www.ccs.neu.edu/home/dorai/t-y<wbr />-scheme/t-y-scheme.html</a></font><font face="serif">. A useful introduction to Scheme; ++includes generator and co-routine solutions to the </font><font face="monospace">same-fringe?</font><font face="serif"> problem.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Michael Sperber, ++<p align="justify"><font face="serif">Michael Sperber, + R. Kent Dybvig, Matthew Flatt, and Anton von Straaten, editors. <i> + + Revised</i><sup><i>6</i></sup><i> Report on the Algorithmic Language +-Scheme</i>. September 26, 2007. </font><font face="monospace"><a href="http://www.r6rs.org/" target="_blank">www.r6rs.org</a></font><font face="serif">. The standard definition of +-the Scheme programming language.</font></font></font></p> ++Scheme</i>. September 26, 2007. </font><font face="monospace"><a href="http://www.r6rs.org" target="_blank">www.r6rs.org</a></font><font face="serif">. The standard definition of ++the Scheme programming language.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">André van ++<p align="justify"><font face="serif">André van + Tonder. <i>Scheme Request for Implementation 45: +-Primitives for Expressing Iterative Lazy Algorithms</i>. </font><font face="monospace"><a href="http://srfi.schemers.org/srfi-45" target="_blank">srfi.schemers.org/srfi-45</a></font><font face="serif">. ++Primitives for Expressing Iterative Lazy Algorithms</i>. </font><font face="monospace"><a href="../srfi-45.html" target="_blank">srfi.schemers.org/srfi-45</a></font><font face="serif">. + April, 2004. Describes the problems inherent in the </font><font face="monospace">promise</font><font face="serif"> + data type of R5RS (also present in R6RS), and provides the alternate </font><font face="monospace">promise</font><font face="serif"> +-data type used in the stream primitives.</font></font></font></p> ++data type used in the stream primitives.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Philip Wadler. +-“How to replace failure by a list of successes,” in <i>Proceedings ++<p align="justify"><font face="serif">Philip Wadler. ++“How to replace failure by a list of successes,” in <i>Proceedings + of the conference on functional programming languages and computer architecture</i>, +-Nancy, France, 1985, pages 113–128. Describes the “list of +-successes” technique for implementing backtracking algorithms using +-streams.</font></font></font></p> ++Nancy, France, 1985, pages 113–128. Describes the “list of ++successes” technique for implementing backtracking algorithms using ++streams.</font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">Philip Wadler, +-Walid Taha, and David MacQueen, “How to add laziness to a strict language +-without even being odd.” 1998 ACM SIGPLAN Workshop on ML, pp. 24ff. </font><font face="monospace"><a href="http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.ps" target="_blank">homepages.inf.ed.ac.uk/wadler<wbr>/papers/lazyinstrict/lazyinstri<wbr>ct.ps</a></font><font face="serif">. Describes odd and even styles ++<p align="justify"><font face="serif">Philip Wadler, ++Walid Taha, and David MacQueen, “How to add laziness to a strict language ++without even being odd.” 1998 ACM SIGPLAN Workshop on ML, pp. 24ff. </font><font face="monospace"><a href="http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.ps" target="_blank">homepages.inf.ed.ac.uk/wadler<wbr />/papers/lazyinstrict/lazyinstri<wbr />ct.ps</a></font><font face="serif">. Describes odd and even styles + of lazy evaluation, and shows how to add lazy evaluation to the strict +-functional language SML. </font></font></font></p> ++functional language SML. </font></p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif">All cited web +-pages visited during September 2007.</font></font></font></p> ++<p align="justify"><font face="serif">All cited web ++pages visited during September 2007.</font></p> + +-<h1><font face="serif"><font face="serif">Copyright</font></font></h1> ++<h2>Copyright</h2> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"> +-Copyright (C) Philip L. Bewig (2007). All Rights Reserved.</font></font></font></p> ++<p align="justify"><font face="serif"> ++Copyright (C) Philip L. Bewig (2007). All Rights Reserved.</font></p> + + <p align="justify"> +-<font face="serif"><font face="serif"><font face="serif">Permission is hereby granted, free of charge, to any person obtaining a ++Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the +-Software is furnished to do so, subject to the following conditions:</font></font></font></p> ++Software is furnished to do so, subject to the following conditions:</p> + + <p align="justify"> +-<font face="serif"><font face="serif"><font face="serif">The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software.</font></font></font></p> ++The above copyright notice and this permission notice shall be included in ++all copies or substantial portions of the Software.</p> + + <p align="justify"> +-<font face="serif"><font face="serif"><font face="serif">THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +-DEALINGS IN THE SOFTWARE.</font></font></font></p> ++DEALINGS IN THE SOFTWARE.</p> + +-<p align="justify"><font face="serif"><font face="serif"><font face="serif"><font face="serif">Several files related to this document are ++<p align="justify"><font face="serif">Several files related to this document are + available from</font> + <font face="monospace">srfi.schemers.org/srfi-41</font><font face="serif">: + A version of this document suitable for printing is available at</font> +-<font face="monospace"><a href="http://srfi.schemers.org/srfi-41/streams.pdf">streams.pdf</a></font><font face="serif">. ++<font face="monospace"><a href="https://srfi.schemers.org/srfi-41/streams.pdf">streams.pdf</a></font><font face="serif">. + The complete source corresponding to the three Appendices is available in files</font> +-<font face="monospace"><a href="http://srfi.schemers.org/srfi-41/streams.ss">streams.ss</a></font><font face="serif">, +-</font><font face="monospace"><a href="http://srfi.schemers.org/srfi-41/primitive.ss">primitive.ss</a></font><font face="serif">, and +-</font><font face="monospace"><a href="http://srfi.schemers.org/srfi-41/derived.ss">derived.ss</a></font><font face="serif">. ++<font face="monospace"><a href="https://srfi.schemers.org/srfi-41/streams.ss">streams.ss</a></font><font face="serif">, ++</font><font face="monospace"><a href="https://srfi.schemers.org/srfi-41/primitive.ss">primitive.ss</a></font><font face="serif">, and ++</font><font face="monospace"><a href="https://srfi.schemers.org/srfi-41/derived.ss">derived.ss</a></font><font face="serif">. + Samples from the text are available at +-</font><font face="monospace"><a href="http://srfi.schemers.org/srfi-41/samples.ss">samples.ss</a></font><font face="serif">, ++</font><font face="monospace"><a href="https://srfi.schemers.org/srfi-41/samples.ss">samples.ss</a></font><font face="serif">, + and a test suite is available at</font> +-<font face="monospace"><a href="http://srfi.schemers.org/srfi-41/r6rs-test.ss">r6rs-test.ss</a></font><font face="serif">. ++<font face="monospace"><a href="https://srfi.schemers.org/srfi-41/r6rs-test.ss">r6rs-test.ss</a></font><font face="serif">. + Source code and tests for R5RS are available at</font> +-<font face="monospace"><a href="http://srfi.schemers.org/srfi-41/r5rs.ss">r5rs.ss</a></font><font face="serif">, +-and</font> <font face="monospace"><a href="http://srfi.schemers.org/srfi-41/r5rs-test.ss">r5rs-test.ss</a></font><font face="serif">.</font></font></font></font></p> ++<font face="monospace"><a href="https://srfi.schemers.org/srfi-41/r5rs.ss">r5rs.ss</a></font><font face="serif">, ++and</font> <font face="monospace"><a href="https://srfi.schemers.org/srfi-41/r5rs-test.ss">r5rs-test.ss</a></font><font face="serif">.</font></p> + +-<hr> +-<address><font face="serif"><font face="serif"><font face="serif">Editor: <a href="mailto:srfi-editors%20at%20srfi%20dot%20schemers%20dot%20org">Michael Sperber</a></font></font></font></address> ++<hr /> ++<address>Editor: <a href="mailto:srfi-editors%20at%20srfi%20dot%20schemers%20dot%20org">Michael Sperber</a></address> + +-</body></html> ++</body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-42.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-42.html +index a3cb664..69f4f79 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-42.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-42.html +@@ -1,48 +1,52 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-42 ┃ ++┃ Commit: e87e982c4f48aedb3c58a27119050c60516016b4 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 42: Eager Comprehensions</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> +- +-SRFI 42: Eager Comprehensions +- +-<H1>Author</H1> +- +-Sebastian Egner +- +-<H1>Status</H1> +- +-<P>This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a +-href="http://srfi.schemers.org/srfi-process.html">here</a>. +-To comments +-this SRFI, please mail to +-<a href="mailto:srfi-42@srfi.schemers.org"> +-<code>srfi-42@srfi.schemers.org</code></a>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html"> +-instructions here</a> to subscribe to the list. You can access +-the discussion via +-<a href="http://srfi.schemers.org/srfi-42/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-42/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-</P> +- <UL> +- <LI>Received: 2003/02/20 +- <LI>Draft: 2003/02/20-2003/04/20 +- <LI>Revised: 2003/07/07 +- <LI>Final: 2003/07/07 +- </UL> +- +-<H1>Abstract</H1> +- +-This SRFI defines a modular and portable mechanism for ++<h1>SRFI 42: Eager Comprehensions</h1> ++ ++<p>by Sebastian Egner</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 42 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-42/srfi-42.html">https://srfi.schemers.org/srfi-42/srfi-42.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+42+at+srfi+dotschemers+dot+org">srfi-42@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-42">archive</a>.</p> ++<ul> ++ <li>Received: 2003-02-20 ++ </li><li>Draft: 2003-02-20--2003-04-20 ++ </li><li>Revised: 2003-07-07 ++ </li><li>Final: 2003-07-07 ++</li></ul> ++ ++<h2>Abstract</h2> ++<p> ++This SRFI defines a modular and portable mechanism for + eager comprehensions extending the algorithmic language Scheme + <a href="#R5RS">[R5RS]</a>. + An eager comprehension is a convenient notation +@@ -50,108 +54,108 @@ for one or more nested or parallel loops generating + a sequence of values, and accumulating this sequence into a result. + In its most simple form, a comprehension according to this SRFI + looks like this: +- +-<a name="example1"></a><blockquote><pre><code>(<a href="#list-ec">list-ec</a> (<a href="#:">:</a> i 5) (* i i)) => (0 1 4 9 16)</code>.</pre></blockquote> +- +-Here, <code>i</code> is a local variable that is sequentially +-bound to the values 0, 1, ..., 4, and the squares of these ++</p> ++<blockquote id="example1"><pre><code>(<a href="#list-ec">list-ec</a> (<a href="#%3A">:</a> i 5) (* i i)) => (0 1 4 9 16)</code>.</pre></blockquote> ++<p> ++Here, <code>i</code> is a local variable that is sequentially ++bound to the values 0, 1, ..., 4, and the squares of these + numbers are collected in a list. + The following example illustrates most conventions of this SRFI + with respect to nesting and syntax: +- +-<a name="example1"></a><blockquote><pre><code>(<a href="#list-ec">list-ec</a> (<a href="#:">:</a> n 1 4) (<a href="#:">:</a> i n) (list n i)) => ((1 0) (2 0) (2 1) (3 0) (3 1) (3 2))</code>.</pre></blockquote> +- ++</p> ++<blockquote><pre><code>(<a href="#list-ec">list-ec</a> (<a href="#%3A">:</a> n 1 4) (<a href="#%3A">:</a> i n) (list n i)) => ((1 0) (2 0) (2 1) (3 0) (3 1) (3 2))</code>.</pre></blockquote> ++<p> + In the example, the variable <code>n</code> is first bound to 1 +-then to 2 and finally to 3, and for each binding of <code>n</code> +-the variable <code>i</code> is bound to the values ++then to 2 and finally to 3, and for each binding of <code>n</code> ++the variable <code>i</code> is bound to the values + 0, 1, ..., <code>n</code>-1 in turn. + The expression <code>(list n i)</code> constructs a two-element list for + each bindings, and the comprehension <code>list-ec</code> collects +-all these results in a list.<P> +- ++all these results in a list. ++</p> ++<p> + The mechanism defined in this SRFI has the following properties: ++</p> ++<ul> + +-<UL> +- +-<LI> +-The set of comprehensions defined for this SRFI is inspired by ++<li> ++The set of comprehensions defined for this SRFI is inspired by + those procedures and macros of <a href="#R5RS">[R5RS, 6.]</a> + leading to natural comprehensions such as + <a href="#list-ec"><code>list-ec</code></a>, + <a href="#append-ec"><code>append-ec</code></a>, + <a href="#sum-ec"><code>sum-ec</code></a>, + <a href="#min-ec"><code>min-ec</code></a>, +-<a href="#every?-ec"><code>every?-ec</code></a>, ++<a href="#every%3F-ec"><code>every?-ec</code></a>, + <a href="#do-ec"><code>do-ec</code></a>, and others. +-Some other natural comprehensions (e.g. <code>gcd-ec</code>) have +-not been included into this SRFI due to their low significance ++Some other natural comprehensions (e.g. <code>gcd-ec</code>) have ++not been included into this SRFI due to their low significance + for most applications. +-On the other hand, a few comprehensions ++On the other hand, a few comprehensions + (<a href="#fold-ec"><code>fold-ec</code></a>, + <a href="#fold3-ec"><code>fold3-ec</code></a>) +-not inspired by <a href="#R5RS">[R5RS]</a> have been ++not inspired by <a href="#R5RS">[R5RS]</a> have been + included due to their broad applicability. +-</LI> ++</li> + +-<LI> +-There are typed generators +-(<a href="#:list"><code>:list</code></a>, <a href="#:list"><code>:string</code></a>, ...) ++<li> ++There are typed generators ++(<a href="#%3Alist"><code>:list</code></a>, <a href="#%3Alist"><code>:string</code></a>, ...) + expecting certain types of objects for their arguments. + These generators usually produce code as efficient as + hand coded <code>do</code>-loops. +-</LI> ++</li> + +-<LI> +-There is also the special generator <a href="#:"><code>:</code></a> +-(read 'run through') ++<li> ++There is also the special generator <a href="#%3A"><code>:</code></a> ++(read 'run through') + dispatching on the value of its argument list at runtime. + In the examples above, one or two integers were used to define a range. + The convenience of omitting the type comes at a certain + performance penalty, both per iteration and during startup of the loop. +-</LI> +- +-<LI> +-Generators can be nested depth-first (as in the example above), +-run in parallel (with an optional <a href="#vars">index variable</a> +-or more generally with <a href="#:parallel"><code>:parallel</code></a>), +-and can be stopped early before (<a href="#:while"><code>:while</code></a>) +-or after (<a href="#:until"><code>:until</code></a>) ++</li> ++ ++<li> ++Generators can be nested depth-first (as in the example above), ++run in parallel (with an optional <a href="#vars">index variable</a> ++or more generally with <a href="#%3Aparallel"><code>:parallel</code></a>), ++and can be stopped early before (<a href="#%3Awhile"><code>:while</code></a>) ++or after (<a href="#%3Auntil"><code>:until</code></a>) + producing the current value. +-</LI> ++</li> + +-<LI> +-The sequence of values can be filtered ++<li> ++The sequence of values can be filtered + (<a href="#if"><code>if</code></a>, <a href="#not"><code>not</code></a>, + <a href="#and"><code>and</code></a>, <a href="#or"><code>or</code></a>), + intermediate commands can be evaluated between + generators (<a href="#begin"><code>begin</code></a>), and +-intermediate variables can be introduced (<a href="#:let"><code>:let</code></a>). +-</LI> +-<LI> ++intermediate variables can be introduced (<a href="#%3Alet"><code>:let</code></a>). ++</li> ++<li> + The mechanism is fully modular. +-This means that no existing macro or procedure needs ++This means that no existing macro or procedure needs + to be modified when adding + <a href="#foo-ec">application-specific comprehensions</a>, +-<a href="#:foo">application-specific typed generators</a>, +-or <a href="#:dfoo">application-specific dispatching generators</a>. +-</LI> +- +-<LI> +-Syntactically, this SRFI uses the +-[<I>outer</I> .. <I>inner</I> | <I>expr</I>] convention, +-meaning that the most right generator (<I>inner</I>) spins fastest ++<a href="#%3Afoo">application-specific typed generators</a>, ++or <a href="#%3Adfoo">application-specific dispatching generators</a>. ++</li> ++ ++<li> ++Syntactically, this SRFI uses the ++[<i>outer</i> .. <i>inner</i> | <i>expr</i>] convention, ++meaning that the most right generator (<i>inner</i>) spins fastest + and is followed by the result expression over which the +-comprehension ranges (<I>expr</I>). ++comprehension ranges (<i>expr</i>). + Refer to the <a href="#convention">Section "Design Rationale"</a>. + Moreover, the syntax is strictly prefix and the naming +-convention <code>my-comprehension-ec</code>, ++convention <code>my-comprehension-ec</code>, + <code>:my-generator</code> is used systematically. +-</LI> ++</li> + +-</UL> +- +-<P> ++</ul> + ++<p> + The remainder of this document is organized as follows. + In section <a href="#rationale">Rationale</a> a brief + introduction is given what the motivation is for this SRFI. +@@ -170,28 +174,29 @@ Finally, the section <a href="#refimpl">Reference + Implementation</a> gives source code for a reference + implementation together with a collection of runnable + examples and a few examples on extensions. ++</p> + +- +-<H1><a name="rationale"></a>Rationale</H1> +- ++<h2 id="rationale">Rationale</h2> ++<p> + The purpose of this SRFI is to provide a compact notation +-for many common cases of loops, in particular those ++for many common cases of loops, in particular those + constructing values for further computation. + The origin of this SRFI is my frustration that + there is no simple for the list of integers +-from 0 to <I>n</I>-1. ++from 0 to <i>n</i>-1. + With this SRFI it is <code>(list-ec (: i n) i)</code>. +-Refer to the collection of examples for the ++Refer to the collection of examples for the + <a href="#refimpl">reference implementation</a> + what it can be used for, and what it should not be used for. +-To give a practically useful example, ++To give a practically useful example, + the following procedure computes the sorted + list of all prime numbers below a certain bound + (you may want to run it yourself to get an idea of + its efficiency): ++</p> + + <blockquote><pre><code> +-(define (eratosthenes n) ; primes in {2..n-1} for n >= 1 ++(define (eratosthenes n) ; primes in {2..n-1} for n >= 1 + (let ((p? (make-string n #\1))) + (do-ec (:range k 2 n) + (if (char=? (string-ref p? k) #\1)) +@@ -199,24 +204,25 @@ its efficiency): + (string-set! p? i #\0) ) + (list-ec (:range k 2 n) (if (char=? (string-ref p? k) #\1)) k) ))</code></pre></blockquote> + +- +-Apart from <I>make simple things simple</I>, ++<p> ++Apart from <i>make simple things simple</i>, + there is no other paradigm involved for this SRFI. + In particular, it is not the ambition to implement the +-powerful <I>lazy</I> list comprehensions of other functional ++powerful <i>lazy</i> list comprehensions of other functional + programming languages in Scheme. + If you are looking for that you may want to refer to + <a href="#SRFI40">[SRFI 40]</a>. + (The usual definition of the stream of all primes does +-in fact also use Eratosthenes' sieve method. +-It is instructive to compare.)<P> +- +-The main focus of the design of this SRFI is portability under ++in fact also use Eratosthenes' sieve method. ++It is instructive to compare.) ++</p> ++<p> ++The main focus of the design of this SRFI is portability under + <a href="#R5RS">[R5RS]</a> and modularity for extension. + Portability is achieved by limiting the features included. + Modularity for generators is achieved by a special +-implementation technique using <I>Continuation +-Passing Style</I> for macros (which I learned from ++implementation technique using <i>Continuation ++Passing Style</i> for macros (which I learned from + Richard Kelsey's implementation of "Macros for writing loops", + <a href="#MWL">[MWL]</a>) and by limiting the + expressive power of generators. +@@ -224,193 +230,199 @@ Modularity for comprehensions requires no additional effort. + As modularity was a major design goal, I hope many people will + find it easy to define their own comprehensions and generators. + As a starting point for doing so, I have included several +-<a href="#ext-examples">suggestions</a> for extensions.<P> +- ++<a href="#ext-examples">suggestions</a> for extensions. ++</p> ++<p> + For a detailed motivation of the design decisions, +-please refer to the <a href="#design">Section "Design Rationale"</a>.<P> ++please refer to the <a href="#design">Section "Design Rationale"</a>. ++</p> + +-<H1><a name="specification"></a>Specification</H1> ++<h2 id="specification">Specification</h2> + +-A comprehensions is a hygienic referentially transparent macro ++<p> ++A comprehension is a hygienic, referentially transparent macro + in the sense of <a href="#R5RS">[R5RS, 4.3.]</a>. +-The macros extend the <code><expression></code>-syntax ++The macros extend the <code><expression></code>-syntax + defined in <a href="#R5RS">[R5RS, 7.1.3.]</a>. +-The main syntactic pattern used for defining a comprehension is ++The main syntactic pattern used for defining a comprehension is + <code><qualifier></code>, representing a generator or a filter. +-It is defined in <a href="#qualifiers">Section "Qualifiers"</a>.<P> +- ++It is defined in <a href="#qualifiers">Section "Qualifiers"</a>.</p><p> ++</p> ++<p> + The most important instances of <code><qualifier></code> are generators. + These are defined in <a href="#generators">Section "Generators"</a>. + Generators come in three flavors, +-as <I>typed generators</I> +-(<a href="#:list"><code>:list</code></a>, +-<a href="#:range"><code>:range</code></a> etc.), +-as <I>the dispatching generator</I> <a href="#:"><code>:</code></a> ++as <i>typed generators</i> ++(<a href="#%3Alist"><code>:list</code></a>, ++<a href="#%3Arange"><code>:range</code></a> etc.), ++as <i>the dispatching generator</i> <a href="#%3A"><code>:</code></a> + (pronounced as 'run through'), +-and as combined and modified generators +-(<a href="#:parallel"><code>:parallel</code></a>, +-<a href="#:while"><code>:while</code></a>, +-<a href="#:until"><code>:until</code></a>). +-Most generators in this SRFI also support an optional ++and as combined and modified generators ++(<a href="#%3Aparallel"><code>:parallel</code></a>, ++<a href="#%3Awhile"><code>:while</code></a>, ++<a href="#%3Auntil"><code>:until</code></a>). ++Most generators in this SRFI also support an optional + <a href="#vars">index variable</a> counting the +-values being generated.<P> +- +-Finally, it is explained how to add a new ++values being generated. ++</p> ++<p> ++Finally, it is explained how to add a new + <a href="#foo-ec">application-specific comprehension</a>, +-how to add a new <a href="#:foo">application-specific typed generator</a>, ++how to add a new <a href="#%3Afoo">application-specific typed generator</a>, + and how to add a new +-<a href="#:dfoo">application-specific dispatching generator</a>. ++<a href="#%3Adfoo">application-specific dispatching generator</a>. + As this concerns code unknown at the time this is being written, + the explanation should not be taken as +-a <I>specification</I> in the literal sense. ++a <i>specification</i> in the literal sense. + It rather suggests a convention to follow in order to + ensure new comprehensions and generators blend seamlessly with +-the ones defined in this SRFI.<P> ++the ones defined in this SRFI. ++</p> + + +-<H2><a name="comprehensions"></a>Comprehensions</H2> ++<h3 id="comprehensions">Comprehensions</h3> + +-<DL> +-<DT><a name="do-ec"></a> ++<dl> ++<dt><a name="do-ec"></a> + <code>(do-ec <qualifier></code>*<code> <command>)</code> +-</DT> ++</dt> + +-<DD> +-Evaluates the <code><command></code> exactly once ++<dd> ++Evaluates the <code><command></code> exactly once + for each binding in the sequence defined by the qualifiers. + If there are no qualifiers <code><command></code> + is evaluated exactly once. + The expression is evaluated for its side-effects only. + The result of the comprehension is unspecified. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="list-ec"></a> ++<dl> ++<dt><a name="list-ec"></a> + <code>(list-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + The list of values obtained by evaluating +-<code><expression></code> once for each binding in the sequence ++<code><expression></code> once for each binding in the sequence + defined by the qualifiers. + If there are no qualifiers the result is the list with +-the value of <code><expression></code>. +-</DD> +-</DL> ++the value of <code><expression></code>. ++</dd> ++</dl> + +-<DL> +-<DT><a name="append-ec"></a> ++<dl> ++<dt><a name="append-ec"></a> + <code>(append-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + The list obtained by appending all values of <code><expression></code>, +-which must all be lists.<BR> ++which must all be lists.<br /> + Think of it as + <code>(apply append (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="string-ec"></a> ++<dl> ++<dt><a name="string-ec"></a> + <code>(string-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-The string of all values of <code><expression></code>.<BR> ++<dd> ++The string of all values of <code><expression></code>.<br /> + Think of it as +-<code>(list->string (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++<code>(list->string (list-ec <qualifier></code>*<code> <expression>))</code>. ++</dd> ++</dl> + +-<DL> +-<DT><a name="string-append-ec"></a> ++<dl> ++<dt><a name="string-append-ec"></a> + <code>(string-append-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + The string obtained by appending all values of <code><expression></code>, +-which must all be strings.<BR> ++which must all be strings.<br /> + Think of it as + <code>(apply string-append (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="vector-ec"></a> ++<dl> ++<dt><a name="vector-ec"></a> + <code>(vector-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-The vector of all values of <code><expression></code>.<BR> ++<dd> ++The vector of all values of <code><expression></code>.<br /> + Think of it as +-<code>(list->vector (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++<code>(list->vector (list-ec <qualifier></code>*<code> <expression>))</code>. ++</dd> ++</dl> + +-<DL> +-<DT><a name="vector-of-length-ec"></a> ++<dl> ++<dt><a name="vector-of-length-ec"></a> + <code>(vector-of-length-ec <k> <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + The vector of all values of <code><expression></code>, + of which there must be exactly <code><k></code>. + This comprehension behaves like <code>vector-ec</code> + but can be implemented more efficiently. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="sum-ec"></a> ++<dl> ++<dt><a name="sum-ec"></a> + <code>(sum-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-The sum of all values of <code><expression></code>.<BR> ++<dd> ++The sum of all values of <code><expression></code>.<br /> + Think of it as + <code>(apply + (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="product-ec"></a> ++<dl> ++<dt><a name="product-ec"></a> + <code>(product-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-The product of all values of <code><expression></code>.<BR> ++<dd> ++The product of all values of <code><expression></code>.<br /> + Think of it as + <code>(apply * (list-ec <qualifier></code>*<code> <expression>))</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="min-ec"></a><a name="max-ec"></> +-<code>(min-ec <qualifier></code>*<code> <expression>)</code><BR> ++<dl> ++<dt><a name="min-ec"></a><a name="max-ec"></a> ++<code>(min-ec <qualifier></code>*<code> <expression>)</code><br /> + <code>(max-ec <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + The minimum and maximum of all values of <code><expression></code>. + The sequence of values must be non-empty. +-Think of these as<BR> +-<code>(apply min (list-ec <qualifier></code>*<code> <expression>))</code><BR> +-<code>(apply max (list-ec <qualifier></code>*<code> <expression>))</code>.<P> +- ++Think of these as<br /> ++<code>(apply min (list-ec <qualifier></code>*<code> <expression>))</code><br /> ++<code>(apply max (list-ec <qualifier></code>*<code> <expression>))</code>. ++</p> ++<p> + If you want to return a default value in case the sequence is empty +-you may want to consider<BR> ++you may want to consider<br /> + <code>(fold3-ec 'infinity <qualifier></code>*<code> <expression> min min)</code>. +-</DD> +-</DL> +- +-<DL> +-<DT><a name="any?-ec"></a> ++</p> ++</dd> ++<dt><a name="any?-ec"></a> + <code>(any?-ec <qualifier></code>*<code> <test>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Tests whether any value of <code><test></code> in the sequence + of bindings specified by the qualifiers is non-<code>#f</code>. + If this is the case, <code>#t</code> is returned, otherwise <code>#f</code>. +@@ -418,106 +430,113 @@ If there are no bindings in the sequence specified by the qualifiers + at all then the result is <code>#f</code>. + The enumeration of values stops after the first non-<code>#f</code> + encountered. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="every?-ec"></a> ++<dl> ++<dt><a name="every?-ec"></a> + <code>(every?-ec <qualifier></code>*<code> <test>)</code> +-</DT> ++</dt> + +-<DD> +-Tests whether all values of <code><test></code> are non-<code>#f</code>. ++<dd> ++Tests whether all values of <code><test></code> are non-<code>#f</code>. + If this is the case, <code>#t</code> is returned, otherwise <code>#f</code>. + If the sequence is empty the result is <code>#t</code>. + Enumeration stops after the first <code>#f</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="first-ec"></a><a name="last-ec"></a><code> +-(first-ec <default> <qualifier></code>*<code> <expression>)<br> ++<dl> ++<dt><a name="first-ec"></a><a name="last-ec"></a><code> ++(first-ec <default> <qualifier></code>*<code> <expression>)<br /> + (last-ec <default> <qualifier></code>*<code> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-The first or last value of <code><expression></code> ++<dd> ++The first or last value of <code><expression></code> + in the sequence of bindings specified by the qualifiers. + Before enumeration, the result is initialized + with the value of <code><default></code>; + so this will be the result if the sequence is empty. +-Enumeration is terminated in <code>first-ec</code> ++Enumeration is terminated in <code>first-ec</code> + when the first value has been computed. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="fold-ec"></a><a name="fold3-ec"></a><code> +-(fold-ec <x0> <qualifier></code>*<code> <expression> <f2>)<br> ++<dl> ++<dt><a name="fold-ec"></a><a name="fold3-ec"></a><code> ++(fold-ec <x0> <qualifier></code>*<code> <expression> <f2>)<br /> + (fold3-ec <x0> <qualifier></code>*<code> <expression> <f1> <f2>)</code> +-</DT> ++</dt> + +-<DD> +-Reduces the sequence <I>x</I>[0], <I>x</I>[1], ..., <I>x</I>[<I>n</I>-1] ++<dd> ++<p> ++Reduces the sequence <i>x</i>[0], <i>x</i>[1], ..., <i>x</i>[<i>n</i>-1] + of values obtained by evaluating <code><expression></code> once + for each binding as specified by <code><qualifier></code>*. +-The arguments <code><x0></code>, <code><f2></code>, ++The arguments <code><x0></code>, <code><f2></code>, + and <code><f1></code>, all syntactically equivalent to +-<code><expression></code>, specify the reduction process.<P> +- ++<code><expression></code>, specify the reduction process. ++</p> ++<p> + The reduction process for <code>fold-ec</code> is defined as follows. +-A reduction variable <code>x</code> is initialized to the value ++A reduction variable <code>x</code> is initialized to the value + of <code><x0></code>, +-and for each <I>k</I> in {0, ..., <I>n</I>-1} the command +-<code>(set! x (<f2> </code><I>x</I>[<I>k</I>]<code> x))</code> +-is evaluated. +-Finally, <code>x</code> is returned as the value of the comprehension.<P> +- ++and for each <i>k</i> in {0, ..., <i>n</i>-1} the command ++<code>(set! x (<f2> </code><i>x</i>[<i>k</i>]<code> x))</code> ++is evaluated. ++Finally, <code>x</code> is returned as the value of the comprehension. ++</p> ++<p> + The reduction process for <code>fold3-ec</code> is different. +-If and only if <I>n</I> = 0, i.e. the sequence is empty, then +-<code><x0></code> is evaluated and returned as the value ++If and only if <i>n</i> = 0, i.e. the sequence is empty, then ++<code><x0></code> is evaluated and returned as the value + of the comprehension. + Otherwise, a reduction variable <code>x</code> is initialized +-to the value of <code>(<f1> </code><I>x</I>[0]<code>)</code>, +-and for each <I>k</I> in {1, ..., <I>n</I>-1} the command +-<code>(set! x (<f2> </code><I>x</I>[<I>k</I>]<code> x))</code> +-is evaluated. +-Finally, <code>x</code> is returned as the value of the comprehension.<P> +- ++to the value of <code>(<f1> </code><i>x</i>[0]<code>)</code>, ++and for each <i>k</i> in {1, ..., <i>n</i>-1} the command ++<code>(set! x (<f2> </code><i>x</i>[<i>k</i>]<code> x))</code> ++is evaluated. ++Finally, <code>x</code> is returned as the value of the comprehension. ++</p> ++<p> + As the order of the arguments suggests, + <code><x0></code> is evaluated outside the scope of the + qualifiers, whereas the reduction expressions involving +-<code><f1></code> and <code><f2></code> are ++<code><f1></code> and <code><f2></code> are + inside the scope of the qualifiers (so they may depend on + any variable introduced by the qualifiers). + Note that <code><f2></code> is evaluated repeatedly, +-with any side-effect or overhead this might have.<P> +- +-The main purpose of these comprehensions is ++with any side-effect or overhead this might have. ++</p> ++<p> ++The main purpose of these comprehensions is + implementing other comprehensions as special cases. + They are generalizations of the procedures + <code>fold</code> and <code>reduce</code> in the sense of +-<a href="#SRFI1">[SRFI 1]</a>. +-(Concerning naming and argument order, please refer to ++<a href="#SRFI1">[SRFI 1]</a>. ++(Concerning naming and argument order, please refer to + the discussion archive of SRFI 1, in particular + the posting <a href="#Folds">[Folds]</a>.) + Note that <code>fold3-ec</code> is defined such that +-<code><x0></code> is only evaluated in case the ++<code><x0></code> is only evaluated in case the + sequence is empty. +-This allows raising an error for the empty sequence, ++This allows raising an error for the empty sequence, + as in the example definition of <code>min-ec</code> below. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> + +-<DL> +-<DT><a name="foo-ec"></a> ++<dl> ++<dt><a name="foo-ec"></a> + <code><application-specific comprehension></code> +-</DT> ++</dt> + +-<DD> +-An important aspect of this SRFI is a modular mechanism ++<dd> ++<p> ++An important aspect of this SRFI is a modular mechanism + to define application-specific comprehensions. +-To create a new comprehension a hygienic macro ++To create a new comprehension a hygienic macro + of this name is defined. + The macro transforms the new comprehension patterns + into instances of <a href="#do-ec"><code>do-ec</code></a>, which is the most +@@ -528,7 +547,7 @@ For example, the following code defines + <a href="#min-ec"><code>min-ec</code></a> + in terms of <a href="#fold-ec"><code>fold-ec</code></a> + and <a href="#fold3-ec"><code>fold3-ec</code></a>: +- ++</p> + <blockquote><pre><code> + (define-syntax list-ec + (syntax-rules () +@@ -539,23 +558,22 @@ and <a href="#fold3-ec"><code>fold3-ec</code></a>: + (syntax-rules () + ((min-ec etc1 etc ...) + (fold3-ec (min) etc1 etc ... min min) )))</code></pre></blockquote> +- ++<p> + Note that the pattern <code>etc1 etc ...</code> matches + the syntax <code><qualifier></code>*<code> <expression></code> +-without separate access to <code><qualifier></code>*<code></code> ++without separate access to <code><qualifier></code>*<code></code> + and <code><expression></code>. + In order to define a comprehension that does need explicit +-access to the <code><expression></code>-part, ++access to the <code><expression></code>-part, + the following method is used. +-First, all qualifiers are collected into a ++First, all qualifiers are collected into a + <a href="#nested"><code>nested</code></a>-qualifier, and then the + 'exactly one qualifier'-case is implemented. + For illustration, the following code defines +-<a href="#fold3-ec"><code>fold3-ec</code></a> in terms of ++<a href="#fold3-ec"><code>fold3-ec</code></a> in terms of + <a href="#do-ec"><code>do-ec</code></a>: +- +-<a name="fold3-ec-example"></a> +-<blockquote><pre><code> ++</p> ++<blockquote id="fold3-ec-example"><pre> + (define-syntax fold3-ec + (syntax-rules (nested) + ((fold3-ec x0 (nested q1 ...) q etc1 etc2 etc3 etc ...) +@@ -573,421 +591,441 @@ For illustration, the following code defines + (begin (set! result (f1 value)) + (set! empty #f) ) + (set! result (f2 value result)) ))) +- (if empty x0 result) ))))</code></pre></blockquote> +- ++ (if empty x0 result) ))))</pre></blockquote> ++<p> + Finally, observe that the newly defined <code>fold3-ec</code> + comprehension inherits all types of qualifiers supported by + <code>do-ec</code>, including all application-specific generators; + no further definitions are necessary. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> + + +-<H2><a name="qualifiers"></a>Qualifiers</H2> ++<h3 id="qualifiers">Qualifiers</h3> + ++<p> + This section defines the syntax <code><qualifier></code>. + The nesting of qualifiers is from left (outer) to right (inner). + In other words, the rightmost generator spins fastest. + The nesting also defines the scope of the variables introduced +-by the generators. ++by the generators. + This implies that inner generators may depend on the variables + of outer generators. +-The sequence of enumeration of values is strictly <I>depth first</I>. +-These conventions are illustrated by the +-first <a href="#example1">example</a>.<P> +- +-The syntax <code><qualifier></code> consists of the following alternatives:<P> ++The sequence of enumeration of values is strictly <i>depth first</i>. ++These conventions are illustrated by the ++first <a href="#example1">example</a>. ++</p> ++<p> ++The syntax <code><qualifier></code> consists of the following alternatives: ++</p> + + +-<DL> +-<DT><a name="generator"></a> ++<dl> ++<dt><a name="generator"></a> + <code><generator></code> +-</DT> ++</dt> + +-<DD> ++<dd> + Enumerates a sequence of bindings of one or more variables. + The scope of the variables starts at the generator and extends + over all subsequent qualifiers and expressions in the comprehension. +-The <code><generator></code>-syntax is defined in ++The <code><generator></code>-syntax is defined in + <a href="#generators">Section "Generators"</a>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="if"></a> ++<dl> ++<dt><a name="if"></a> + <code>(if <test>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Filters the sequence of bindings by testing if + <code><test></code> evaluates to non-<code>#f</code>. + Only for those bindings for which this is the case, + the subsequent qualifiers of the comprehension are evaluated. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="not"></a><a name="and"></a><a name="or"></a><code> +-(not <test>)<br> +-(and <test></code>*<code>)<br> ++<dl> ++<dt><a name="not"></a><a name="and"></a><a name="or"></a><code> ++(not <test>)<br /> ++(and <test></code>*<code>)<br /> + (or <test></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Abbreviated notations for filters of the form + <code>(if (not <test>))</code>, + <code>(if (and <test></code>*<code>))</code>, and + <code>(if (or <test></code>*<code>))</code>. + These represent frequent cases of filters. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="begin"></a> ++<dl> ++<dt><a name="begin"></a> + <code>(begin <sequence>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Evaluate <code><sequence></code>, consisting of + <code><command></code>*<code> <expression></code>, +-once for each binding of the variables defined by the ++once for each binding of the variables defined by the + previous qualifiers in the comprehension. + Using this qualifier, side effects can be inserted + into the body of a comprehension. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name="nested"></a> ++<dl> ++<dt><a name="nested"></a> + <code>(nested <qualifier></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + A syntactic construct to group qualifiers. +-The meaning of a qualifier according to the +-<code>nested</code>-syntax is the same as ++The meaning of a qualifier according to the ++<code>nested</code>-syntax is the same as + inserting <code><qualifier></code>* + into the enclosing comprehension. + This construct can be used to reduce comprehensions with several + qualifiers into a form with exactly one qualifier. +-</DD> +-</DL> ++</dd> ++</dl> + + +-<H2><a name="generators"></a>Generators</H2> +- ++<h3 id="generators">Generators</h3> ++<p> + This section defines the syntax <code><generator></code>. +-Each generator defines a sequence of bindings through ++Each generator defines a sequence of bindings through + which one or more variables are run. +-The scope of the variables begins after the closing ++The scope of the variables begins after the closing + parenthesis of the generator expression and extends +-to the end of the comprehension it is part of.<P> +- +-<a name="vars"></a>The variables defined by the generators +-are specified using the syntax<P> +- ++to the end of the comprehension it is part of. ++</p> ++<p> ++<a name="vars"></a>The variables defined by the generators ++are specified using the syntax ++</p> + <blockquote><pre> + <code><vars> --> <variable1></code> [ <code>(index <variable2>)</code> ],</pre></blockquote> + ++<p> + where <code><variable1></code> runs through the values in +-the sequence defined by the generator, and the optional +-<code><variable2></code> is an exact integer-valued ++the sequence defined by the generator, and the optional ++<code><variable2></code> is an exact integer-valued + index variable counting the values (starting from 0). + The names of the variables must be distinct. +-The following example illustrates the index variable:<P> +- ++The following example illustrates the index variable: ++</p> + <blockquote><pre><code> +-(list-ec (: x (index i) "abc") (list x i)) => ((#\a 0) (#\b 1) (#\c 2))</code></pre></blockquote> ++(list-ec (: x (index i) "abc") (list x i)) => ((#\a 0) (#\b 1) (#\c 2))</code></pre></blockquote> + ++<p> + Unless defined otherwise, all generators make sure that the + expressions provided for their syntactic arguments are + evaluated exactly once, before enumeration begins. + Moreover, it may be assumed that the generators do not + copy the code provided for their arguments, because that + could lead to exponential growth in code size. +-Finally, it is possible to assign a value to the variables +-defined by a generator, but the effect of this assignment +-is unspecified.<P> +- +-The syntax <code><generator></code> consists of the following alternatives:<P> ++Finally, it is possible to assign a value to the variables ++defined by a generator, but the effect of this assignment ++is unspecified. ++</p> ++<p> ++The syntax <code><generator></code> consists of the following alternatives: ++</p> + +-<DL> +-<DT><a name=":"></a> ++<dl> ++<dt><a name=":"></a> + <code>(: <vars> <arg1> <arg></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + First the expressions <code><arg1> <arg></code>* +-are evaluated into <I>a</I>[1] <I>a</I>[2] ... <I>a</I>[<I>n</I>] ++are evaluated into <i>a</i>[1] <i>a</i>[2] ... <i>a</i>[<i>n</i>] + and then a global dispatch procedure is used to dispatch on + the number and types of the arguments and run the resulting + generator. +- +-<a name=":-dispatch"></a> +-Initially (after loading the SRFI), +-the following cases are recognized:<P> +- +-<TABLE> +- +-<TR> +-<TD><a href="#:list"><code>:list</code></a> +-<TD>if +-<TD>for all <I>i</I> in {1..<I>n</I>}: +-<code>(list? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:string"><code>:string</code></a> +-<TD>if +-<TD>for all <I>i</I> in {1..<I>n</I>}: +-<code>(string? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:vector"><code>:vector</code></a> +-<TD>if +-<TD>for all <I>i</I> in {1..<I>n</I>}: +-<code>(vector? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:range"><code>:range</code></a> +-<TD>if +-<TD><I>n</I> in {1..3} and +-for all <I>i</I> in {1..<I>n</I>}: +-<code>(integer? </code><I>a</I>[<I>i</I>]<code>)</code> and +-<code>(exact? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:real-range"><code>:real-range</code></a> +-<TD>if +-<TD><I>n</I> in {1..3} and +-for all <I>i</I> in {1..<I>n</I>}: +-<code>(real? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:char-range"><code>:char-range</code></a> +-<TD>if +-<TD><I>n</I> = 2 and +-for all <I>i</I> in {1, 2}: +-<code>(char? </code><I>a</I>[<I>i</I>]<code>)</code>. +-</TR> +- +-<TR> +-<TD><a href="#:port"><code>:port</code></a> +-<TD>if +-<TD><I>n</I> in {1,2} and +-<code>(input-port? </code><I>a</I>[1]<code>)</code> and +-<code>(procedure? </code><I>a</I>[2]<code>)</code>. +-</TR> +- +-</TABLE><P> +- ++</p> ++<p id=":-dispatch"> ++Initially (after loading the SRFI), ++the following cases are recognized: ++</p> ++<table> ++ ++<tr> ++<td><a href="#%3Alist"><code>:list</code></a> ++</td><td>if ++</td><td>for all <i>i</i> in {1..<i>n</i>}: ++<code>(list? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Astring"><code>:string</code></a> ++</td><td>if ++</td><td>for all <i>i</i> in {1..<i>n</i>}: ++<code>(string? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Avector"><code>:vector</code></a> ++</td><td>if ++</td><td>for all <i>i</i> in {1..<i>n</i>}: ++<code>(vector? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Arange"><code>:range</code></a> ++</td><td>if ++</td><td><i>n</i> in {1..3} and ++for all <i>i</i> in {1..<i>n</i>}: ++<code>(integer? </code><i>a</i>[<i>i</i>]<code>)</code> and ++<code>(exact? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Areal-range"><code>:real-range</code></a> ++</td><td>if ++</td><td><i>n</i> in {1..3} and ++for all <i>i</i> in {1..<i>n</i>}: ++<code>(real? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Achar-range"><code>:char-range</code></a> ++</td><td>if ++</td><td><i>n</i> = 2 and ++for all <i>i</i> in {1, 2}: ++<code>(char? </code><i>a</i>[<i>i</i>]<code>)</code>. ++</td></tr> ++ ++<tr> ++<td><a href="#%3Aport"><code>:port</code></a> ++</td><td>if ++</td><td><i>n</i> in {1,2} and ++<code>(input-port? </code><i>a</i>[1]<code>)</code> and ++<code>(procedure? </code><i>a</i>[2]<code>)</code>. ++</td></tr> ++ ++</table> ++<p> + <a name="make-initial-:-dispatch"></a><a name=":-dispatch-ref"></a><a name=":-dispatch-set!"></a> +-The current dispatcher can be retrieved as +-<code>(:-dispatch-ref)</code>, a new dispatcher <I>d</I> ++The current dispatcher can be retrieved as ++<code>(:-dispatch-ref)</code>, a new dispatcher <i>d</i> + can be installed by +-<code>(:-dispatch-set! </code><I>d</I><code>)</code> ++<code>(:-dispatch-set! </code><i>d</i><code>)</code> + yielding an unspecified result, + and a copy of the initial dispatcher can be obtained as + <code>(make-initial-:-dispatch)</code>. +-Please refer to the section <a href="#:dfoo-global">below</a> ++Please refer to the section <a href="#%3Adfoo-global">below</a> + for recommendation how to add cases to the dispatcher. +-</DD> +-</DL> ++</p> ++</dd> + +-<DL> +-<DT><a name=":list"></a><a name=":string"></a><a name=":vector"></a><code> +-(:list <vars> <arg1> <arg></code>*<code>)<br> +-(:string <vars> <arg1> <arg></code>*<code>)<br> ++<dt><a name=":list"></a><a name=":string"></a><a name=":vector"></a><code> ++(:list <vars> <arg1> <arg></code>*<code>)<br /> ++(:string <vars> <arg1> <arg></code>*<code>)<br /> + (:vector <vars> <arg1> <arg></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Run through one or more lists, strings, or vectors. +-First all expressions in <code><arg1> <arg></code>* ++First all expressions in <code><arg1> <arg></code>* + are evaluated and then all elements of the resulting values + are enumerated from left to right. + One can think of it as first appending all arguments and + then enumerating the combined object. +-As a clarifying example, consider<BR> +-<code>(list-ec (:string c (index i) "a" "b") (cons c i))</code> => ++As a clarifying example, consider<br /> ++<code>(list-ec (:string c (index i) "a" "b") (cons c i))</code> => + <code>((#\a . 0) (#\b . 1))</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":integers"></a> ++<dl> ++<dt><a name=":integers"></a> + <code>(:integers <vars>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Runs through the sequence 0, 1, 2, ... of non-negative integers. +-This is most useful in combination with +-<a href="#:parallel"><code>:parallel</code></a>, +-<a href="#:while"><code>:while</code></a>, and +-<a href="#:until"><code>:until</code></a> or with ++This is most useful in combination with ++<a href="#%3Aparallel"><code>:parallel</code></a>, ++<a href="#%3Awhile"><code>:while</code></a>, and ++<a href="#%3Auntil"><code>:until</code></a> or with + a non-local exit in the body of the comprehension. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":range"></a><code> +-(:range <vars> <stop>)<br> +-(:range <vars> <start> <stop>)<br> ++<dl> ++<dt><a name=":range"></a><code> ++(:range <vars> <stop>)<br /> ++(:range <vars> <start> <stop>)<br /> + (:range <vars> <start> <stop> <step>)</code> +-</DT> +- +-<DD> +-Runs through a range of exact rational numbers.<P> ++</dt> + ++<dd> ++<p> ++Runs through a range of exact rational numbers. ++</p> ++<p> + The form <code>(:range <vars> <stop>)</code> + evaluates the expression <code><stop></code>, +-which must result in an exact integer <I>n</I>, +-and runs through the finite sequence 0, 1, 2, ..., <I>n</I>-1. +-If <I>n</I> is zero or negative the sequence is empty.<P> ++which must result in an exact integer <i>n</i>, ++and runs through the finite sequence 0, 1, 2, ..., <i>n</i>-1. ++If <i>n</i> is zero or negative the sequence is empty.</p><p> + + The form <code>(:range <vars> <start> <stop>)</code> +-evaluates the expressions <code><start></code> and ++evaluates the expressions <code><start></code> and + <code><stop></code>, +-which must result in exact integers <I>a</I> and <I>b</I>, +-and runs through the finite sequence +-<I>a</I>, <I>a</I>+1, <I>a</I>+2, ..., <I>b</I>-1. +-If <I>b</I> is less or equal <I>a</I> then the sequence is empty.<P> +- ++which must result in exact integers <i>a</i> and <i>b</i>, ++and runs through the finite sequence ++<i>a</i>, <i>a</i>+1, <i>a</i>+2, ..., <i>b</i>-1. ++If <i>b</i> is less or equal <i>a</i> then the sequence is empty. ++</p> ++<p> + The form <code>(:range <vars> <start> <stop> <step>)</code> +-first evaluates the expressions <code><start></code>, ++first evaluates the expressions <code><start></code>, + <code><stop></code>, and <code><step></code>, +-which must result in exact integers <I>a</I>, <I>b</I>, and <I>s</I> +-such that <I>s</I> is unequal to zero. ++which must result in exact integers <i>a</i>, <i>b</i>, and <i>s</i> ++such that <i>s</i> is unequal to zero. + Then the sequence +-<I>a</I>, <I>a</I> + <I>s</I>, <I>a</I> + 2 <I>s</I>, ..., <I>a</I> + (<I>n</I>-1) <I>s</I> +-is enumerated where <I>n</I> = ceil((<I>b</I>-<I>a</I>)/<I>s</I>). +-In other words, the sequence starts at <I>a</I>, increments by <I>s</I>, +-and stops when the next value would reach or cross <I>b</I>. +-If <I>n</I> is zero or negative the sequence is empty. +-</DD> +-</DL> +- +-<DL> +-<DT><a name=":real-range"></a><code> +-(:real-range <vars> <stop>)<br> +-(:real-range <vars> <start> <stop>)<br> ++<i>a</i>, <i>a</i> + <i>s</i>, <i>a</i> + 2 <i>s</i>, ..., <i>a</i> + (<i>n</i>-1) <i>s</i> ++is enumerated where <i>n</i> = ceil((<i>b</i>-<i>a</i>)/<i>s</i>). ++In other words, the sequence starts at <i>a</i>, increments by <i>s</i>, ++and stops when the next value would reach or cross <i>b</i>. ++If <i>n</i> is zero or negative the sequence is empty. ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt><a name=":real-range"></a><code> ++(:real-range <vars> <stop>)<br /> ++(:real-range <vars> <start> <stop>)<br /> + (:real-range <vars> <start> <stop> <step>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + Runs through a range of real numbers using an explicit index variable. + This form of range enumeration avoids accumulation of rounding errors +-and is the one to use if any of the numbers defining the range is +-inexact, not an integer, or a bignum of large magnitude.<P> +- ++and is the one to use if any of the numbers defining the range is ++inexact, not an integer, or a bignum of large magnitude. ++</p> ++<p> + Providing default value 0 for <code><start></code> and + 1 for <code><step></code>, the generator first + evaluates <code><start></code>, <code><stop></code>, + and <code><step></code>, which must result in reals +-<I>a</I>, <I>b</I>, and <I>s</I> such that +-<I>n</I> = (<I>b</I>-<I>a</I>)/<I>s</I> is also representable ++<i>a</i>, <i>b</i>, and <i>s</i> such that ++<i>n</i> = (<i>b</i>-<i>a</i>)/<i>s</i> is also representable + as a real. + Then the sequence 0, 1, 2, ... is enumerated while the +-current value <I>i</I> is less than <I>n</I>, and the ++current value <i>i</i> is less than <i>n</i>, and the + variable in <code><vars></code> is bound to the +-value <I>a</I> + <I>i</I> <I>s</I>. +-If any of the values <I>a</I>, <I>b</I>, or <I>s</I> is ++value <i>a</i> + <i>i</i> <i>s</i>. ++If any of the values <i>a</i>, <i>b</i>, or <i>s</i> is + non-exact then all values in the sequence are non-exact. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> ++ + +-<DL> +-<DT><a name=":char-range"></a> ++<dl> ++<dt><a name=":char-range"></a> + <code>(:char-range <vars> <min> <max>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Runs through a range of characters. + First <code><min></code> and <code><max></code> are +-evaluated, which must result in two characters <I>a</I> and <I>b</I>. +-Then the sequence of characters +-<I>a</I>, <I>a</I>+1, <I>a</I>+2, ..., <I>b</I> ++evaluated, which must result in two characters <i>a</i> and <i>b</i>. ++Then the sequence of characters ++<i>a</i>, <i>a</i>+1, <i>a</i>+2, ..., <i>b</i> + is enumerated in the order defined by <code>char<=?</code> + in the sense of <a href="#R5RS">[R5RS, 6.3.4.]</a>. +-If <I>b</I> is smaller than <I>a</I> then the sequence is empty. +-(Note that <I>b</I> is included in the sequence.) +-</DD> +-</DL> +- +-<DL> +-<DT><a name=":port"></a> +-<code>(:port <vars> <port>)</code><BR> ++If <i>b</i> is smaller than <i>a</i> then the sequence is empty. ++(Note that <i>b</i> is included in the sequence.) ++</dd> ++</dl> ++ ++<dl> ++<dt><a name=":port"></a> ++<code>(:port <vars> <port>)</code><br /> + <code>(:port <vars> <port> <read-proc>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Reads from the port until the eof-object is read. +-Providing the default <code>read</code> for ++Providing the default <code>read</code> for + <code><read-proc></code>, the generator first +-evaluates <code><port></code> and ++evaluates <code><port></code> and + <code><read-proc></code>, which must result +-in an input port <I>p</I> and a procedure <I>r</I>. ++in an input port <i>p</i> and a procedure <i>r</i>. + Then the variable is run through the sequence obtained +-by <code>(</code><I>r</I><code> </code><I>p</I><code>)</code> ++by <code>(</code><i>r</i><code> </code><i>p</i><code>)</code> + while the result does not satisfy <code>eof-object?</code>. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":dispatched"></a> ++<dl> ++<dt><a name=":dispatched"></a> + <code>(:dispatched <vars> <dispatch> <arg1> <arg></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + Runs the variables through a sequence defined by <code><dispatch></code> + and <code><arg1> <arg></code>*. + The purpose of <code>:dispatched</code> is implementing + dispatched generators, in particular the predefined dispatching +-generator <a href="#:"><code>:</code></a>.<P> +- ++generator <a href="#%3A"><code>:</code></a>. ++</p> ++<p> + The working of <code>:dispatched</code> is as follows. + First <code><dispatch></code> and + <code><arg1> <arg></code>* are evaluated, +-resulting in a procedure <I>d</I> (the 'dispatcher') and +-the values <I>a</I>[1] <I>a</I>[2] ... <I>a</I>[<I>n</I>]. +-Then +-<code>(</code><I>d</I><code> (list </code><I>a</I>[1] <I>a</I>[2] ... <I>a</I>[<I>n</I>] <code>))</code> +-is evaluated, resulting in a value <I>g</I>. +-If <I>g</I> is not a procedure then the dispatcher ++resulting in a procedure <i>d</i> (the 'dispatcher') and ++the values <i>a</i>[1] <i>a</i>[2] ... <i>a</i>[<i>n</i>]. ++Then ++<code>(</code><i>d</i><code> (list </code><i>a</i>[1] <i>a</i>[2] ... <i>a</i>[<i>n</i>] <code>))</code> ++is evaluated, resulting in a value <i>g</i>. ++If <i>g</i> is not a procedure then the dispatcher + did not recognize the argument list and an error is raised. +-Otherwise the 'generator procedure' <I>g</I> is used ++Otherwise the 'generator procedure' <i>g</i> is used + to run <code><vars></code> through a sequence of values. +-The sequence defined by <I>g</I> is obtained by repeated +-evaluation of <code>(</code><I>g</I> <I>empty</I><code>)</code> +-until the result is <I>empty</I>. +-In other words, <I>g</I> indicates the end of the sequence by +-returning its only argument, for which the caller has provided +-an object distinct from anything <I>g</I> can produce. ++The sequence defined by <i>g</i> is obtained by repeated ++evaluation of <code>(</code><i>g</i> <i>empty</i><code>)</code> ++until the result is <i>empty</i>. ++In other words, <i>g</i> indicates the end of the sequence by ++returning its only argument, for which the caller has provided ++an object distinct from anything <i>g</i> can produce. + (Generator procedures are state based, they are no such noble things +-as streams in the sense of <a href="#SRFI40">SRFI 40</a>.)<P> +- +-<a name=":generator-proc"></a> ++as streams in the sense of <a href="#SRFI40">SRFI 40</a>.) ++</p> ++<p id=":generator-proc"> + The definition of dispatchers is greatly simplified by the + macro <code>:generator-proc</code> that constructs a generator + procedure from a typed generator. + Let <code>(g var arg1 arg ...)</code> be an instance of + the <code><generator></code> syntax, for example an +-<a href="#:foo">application-specific typed generator</a>, ++<a href="#%3Afoo">application-specific typed generator</a>, + with a single variable <code>var</code> and no index variable. + Then +- ++</p> + <blockquote><code> +-(:generator-proc (g arg1 arg ...)) => </code><I>g</I>,</blockquote> +- +-where the generator procedure <I>g</I> runs through the list +-<code>(list-ec (g var arg1 arg ...) var)</code>.<P> ++(:generator-proc (g arg1 arg ...)) => </code><i>g</i>,</blockquote> ++<p> ++where the generator procedure <i>g</i> runs through the list ++<code>(list-ec (g var arg1 arg ...) var)</code>. ++</p> + +-<a name=":dfoo"></a> +-<I>Adding an application-specific dispatching generator</I>. ++<p id=":dfoo"> ++<i>Adding an application-specific dispatching generator</i>. + In order to define a new dispatching generator (say <code>:my</code>) + first a dispatching procedure (say <code>:my-dispatch</code>) is defined. + The dispatcher will be called with a single (!) argument +@@ -998,9 +1036,9 @@ when it is called with the empty list. + Otherwise (if there is at least one value to dispatch on), + the dispatcher must either return a generator procedure + or <code>#f</code> (= no interest). +-As an example, the following skeleton code defines a dispatcher +-similar to the initial dispatcher of <a href="#:"><code>:</code></a>: +- ++As an example, the following skeleton code defines a dispatcher ++similar to the initial dispatcher of <a href="#%3A"><code>:</code></a>: ++</p> + <pre> + (define (:my-dispatch args) + (case (length args) +@@ -1011,28 +1049,28 @@ similar to the initial dispatcher of <a href="#:"><code>:</code></a>: + (:generator-proc (:list a1)) ) + ((string? a1) + (:generator-proc (:string a1)) ) +- <I>...more unary cases...</I> ++ <i>...more unary cases...</i> + (else + #f )))) + ((2) (let ((a1 (car args)) (a2 (cadr args))) + (cond + ((and (list? a1) (list? a2)) + (:generator-proc (:list a1 a2)) ) +- <I>...more binary cases...</I> ++ <i>...more binary cases...</i> + (else + #f )))) +- <I>...more arity cases...</I> ++ <i>...more arity cases...</i> + (else + (cond + ((every?-ec (:list a args) (list? a)) + (:generator-proc (:list (apply append args))) ) +- <I>...more large variable arity cases...</I> ++ <i>...more large variable arity cases...</i> + (else + #f )))))</pre> +- +-Once the dispatcher has been defined, the following macro ++<p> ++Once the dispatcher has been defined, the following macro + implements the new dispatching generator: +- ++</p> + <pre> + (define-syntax :my + (syntax-rules (index) +@@ -1040,83 +1078,85 @@ implements the new dispatching generator: + (:dispatched cc var (index i) :my-dispatch arg1 arg ...) ) + ((:my cc var arg1 arg ...) + (:dispatched cc var :my-dispatch arg1 arg ...) )))</pre> +- ++<p> + This method of extension yields complete control of the dispatching process. + Other modules can only add cases to <code>:my</code> +-if they have access to <code>:my-dispatch</code>.<P> +- +-<a name=":dfoo-global"></a> +-<I>Extending the predefined dispatched generator</I>. ++if they have access to <code>:my-dispatch</code>. ++</p> ++<p id=":dfoo-global"> ++<i>Extending the predefined dispatched generator</i>. + An alternative to adding a new dispatched generators is extending +-the predefined generator <a href="#:"><code>:</code></a>. +-Technically, extending <a href="#:"><code>:</code></a> means ++the predefined generator <a href="#%3A"><code>:</code></a>. ++Technically, extending <a href="#%3A"><code>:</code></a> means + installing a new global dispatching procedure using +-<a href="#:-dispatch-set!"><code>:-dispatch-set!</code></a> ++<a href="#%3A-dispatch-set!"><code>:-dispatch-set!</code></a> + as described above. +- +-<a name="dispatch-union"></a> ++</p> ++<p id="dispatch-union"> + In most cases, however, the already installed dispatcher should +-be extended by new cases. ++be extended by new cases. + The following procedure is a utility for doing so: +- +-<pre>(dispatch-union <I>d1</I> <I>d2</I>) => <I>d</I>,</pre> +- +-where the new dispatcher <I>d</I> recognizes the union of the +-cases recognized by the dispatchers <I>d1</I> and <I>d2</I>. ++</p> ++<pre>(dispatch-union <i>d1</i> <i>d2</i>) => <i>d</i>,</pre> ++<p> ++where the new dispatcher <i>d</i> recognizes the union of the ++cases recognized by the dispatchers <i>d1</i> and <i>d2</i>. + The new dispatcher always tries both component dispatchers + and raises an error in case of conflict. +-The identification returned by <code>(</code><I>d</I><code>)</code> ++The identification returned by <code>(</code><i>d</i><code>)</code> + is the concatenation of the component identifications +-<code>(</code><I>d1</I><code>)</code> and +-<code>(</code><I>d2</I><code>)</code>, enclosed in lists ++<code>(</code><i>d1</i><code>)</code> and ++<code>(</code><i>d2</i><code>)</code>, enclosed in lists + if necessary. + For illustration, consider the following code: +- ++</p> + <pre> + (define (example-dispatch args) + (cond + ((null? args) + 'example ) + ((and (= (length args) 1) (symbol? (car args)) ) +- (:generator-proc (:string (symbol->string (car args)))) ) ++ (:generator-proc (:string (symbol->string (car args)))) ) + (else + #f ))) + + (:-dispatch-set! (dispatch-union (:-dispatch-ref) example-dispatch))</pre> +- ++<p> + After evaluation of this code, the following example will work: +- +-<pre>(list-ec (: c 'abc) c) => (#\a #\b #\c)</pre> +- +-Adding cases to <a href="#:"><code>:</code></a> is particularly useful ++</p> ++<pre>(list-ec (: c 'abc) c) => (#\a #\b #\c)</pre> ++<p> ++Adding cases to <a href="#%3A"><code>:</code></a> is particularly useful + for frequent cases of interactive input. + Be warned, however, that the advantage of global extension also carries + the danger of conflicts, unexpected side-effects, and slow dispatching. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> ++ + +-<DL> +-<DT><a name=":do"></a><code> +-(:do (<lb></code>*<code>) <ne1?> (<ls></code>*<code>))<br> ++<dl> ++<dt><a name=":do"></a><code> ++(:do (<lb></code>*<code>) <ne1?> (<ls></code>*<code>))<br /> + (:do (let (<ob></code>*<code>) <oc></code>*<code>) (<lb></code>*<code>) <ne1?> (let (<ib></code>*<code>) <ic></code>*<code>) <ne2?> (<ls></code>*<code>))</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Defines a generator in terms of a named-<code>let</code>, + optionally decorated with inner and outer <code>let</code>s. + This generator is for defining other generators. + (In fact, the reference implementation transforms any other + generator into an instance of fully decorated <code>:do</code>.) +-The generator is a compromise between expressive power ++The generator is a compromise between expressive power + (more flexible loops) and fixed structure (necessary + for merging and modifying generators). +-In the fully decorated form, the syntactic variables ++In the fully decorated form, the syntactic variables + <code><ob></code> (outer binding), + <code><oc></code> (outer command), + <code><lb></code> (loop binding), + <code><ne1?></code> (not-end1?), + <code><ib></code> (inner binding), +-<code><ic></code> (inner command), ++<code><ic></code> (inner command), + <code><ne2?></code> (not-end2?), and + <code><ls></code> (loop step) + define the following loop skeleton: +@@ -1124,11 +1164,11 @@ define the following loop skeleton: + <pre> + (let (<ob>*) + <oc>* +- (let loop (<lb>*) ++ (let loop (<lb>*) + (if <ne1?> + (let (<ib>*) + <ic>* +- <I>payload</I> ++ <i>payload</i> + (if <ne2?> + (loop <ls>*) ))))),</pre> + +@@ -1139,120 +1179,129 @@ i.e. they do not begin with a <code><definition></code>. + The latter requirement allows the code generator to + produce more efficient code for special cases by + removing empty <code>let</code>-expressions altogether. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":let"></a> ++<dl> ++<dt><a name=":let"></a> + <code>(:let <vars> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-Runs through the sequence consisting of the value of ++<dd> ++Runs through the sequence consisting of the value of + <code><expression></code>, only. + This is the same as + <code>(:list <vars> (list <expression>))</code>. + If an index variable is specified, its value is 0. +-The <code>:let</code>-generator can be used to introduce ++The <code>:let</code>-generator can be used to introduce + an intermediate variable depending on outer generators. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":parallel"></a> ++<dl> ++<dt><a name=":parallel"></a> + <code>(:parallel <generator></code>*<code>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> + Runs several generators in parallel. + This means that the next binding in the sequence is obtained + by advancing each generator in <code><generator></code>* + by one step. + The parallel generator terminates when any of its component + generators terminates. +-The generators share a common scope for the variables ++The generators share a common scope for the variables + they introduce. +-This implies that the names of the variables introduced ++This implies that the names of the variables introduced + by the various generators must be distinct. +-</DD> +-</DL> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":while"></a> ++<dl> ++<dt><a name=":while"></a> + <code>(:while <generator> <expression>)</code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + Runs <code><generator></code> while <code><expression></code> + evaluates to non-<code>#f</code>. + The guarding expression is included in the scope +-of the variables introduced by the generator.<P> +- ++of the variables introduced by the generator. ++</p> ++<p> + Note the distinction between the filter <code>if</code> and + the modified generator expressed by <code>:while</code>. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> ++ + +-<DL> +-<DT><a name=":until"></a> ++<dl> ++<dt><a name=":until"></a> + <code>(:until <generator> <expression>)</code> +-</DT> ++</dt> + +-<DD> +-Runs <code><generator></code> until after ++<dd> ++<p> ++Runs <code><generator></code> until after + <code><expression></code> has evaluated to non-<code>#f</code>. + The guarding expression is included in the scope +-of the variables introduced by the generator.<P> +- +-Note the distinction between <code>:while</code>, stopping <I>at</I> +-a certain condition, and <code>:until</code>, stopping <I>after</I> ++of the variables introduced by the generator. ++</p> ++<p> ++Note the distinction between <code>:while</code>, stopping <i>at</i> ++a certain condition, and <code>:until</code>, stopping <i>after</i> + a certain condition has occurred. The latter implies that the binding + that has triggered termination has been processed by the comprehension. +-</DD> +-</DL> ++</p> ++</dd> ++</dl> + +-<DL> +-<DT><a name=":foo"></a> ++<dl> ++<dt><a name=":foo"></a> + <code><application-specific typed generator></code> +-</DT> ++</dt> + +-<DD> ++<dd> ++<p> + An important aspect of this SRFI is a modular mechanism to + define new typed generators. + To define a new typed generator a hygienic referentially + transparent macro of the same name is defined to transform +-the generator pattern into an instance of the +-<a href="#:do"><code>:do</code></a>-generator. ++the generator pattern into an instance of the ++<a href="#%3Ado"><code>:do</code></a>-generator. + The extension is fully modular, meaning that no other + macro has to be modified to add the new generator. + This is achieved by defining the new macro in +-<I>Continuation Passing Style</I>, as in <a href="#MWL">[MWL]</a>.<P> +- ++<i>Continuation Passing Style</i>, as in <a href="#MWL">[MWL]</a>. ++</p> ++<p> + Technically, this works as follows. +-Assume the generator syntax <code>(:mygen <var> <arg>)</code> ++Assume the generator syntax <code>(:mygen <var> <arg>)</code> + is to be implemented, for example running the variable <code><var></code> + through the list <code>(reverse <arg>)</code>. +-The following definition implements <code>:mygen</code> +-in terms of <a href="#:list"><code>:list</code></a> +-using the additional syntactic variable <code>cc</code> +-(read <I>current continuation</I>): +- ++The following definition implements <code>:mygen</code> ++in terms of <a href="#%3Alist"><code>:list</code></a> ++using the additional syntactic variable <code>cc</code> ++(read <i>current continuation</i>): ++</p> + <pre> + (define-syntax :mygen + (syntax-rules () + ((:mygen cc var arg) + (:list cc var (reverse arg)) )))</pre> +- +-After this definition, any comprehension will accept ++<p> ++After this definition, any comprehension will accept + the <code>:mygen</code>-generator and produce the + proper code for it. +-This works as follows. ++This works as follows. + When a comprehension sees something of the form + <code>(g arg ...)</code> in the position of a + <code><qualifier></code> then it will +-transform the entire comprehension into ++transform the entire comprehension into + <code>(g (continue ...) arg ...)</code>. +-This effectively 'transfers control' to the ++This effectively 'transfers control' to the + macro <code>g</code>, for example <code>:mygen</code>. + The macro <code>g</code> has full control of + the transformation, but eventually it should +@@ -1263,145 +1312,152 @@ by the <code>:list</code>-macro. + The macro <code>:do</code> finally transforms + into <code>(continue ... (:do etc ...))</code>. + As <code>continue</code> has been chosen by the +-macro implementing the comprehension, ++macro implementing the comprehension, + it can regain control and proceed +-with other qualifiers.<P> +- +-In order to ensure consistency of new generators ++with other qualifiers. ++</p> ++<p> ++In order to ensure consistency of new generators + with the ones defined in this SRFI, a few conventions + are in order. +-Firstly, the generator patterns begin with one or more ++Firstly, the generator patterns begin with one or more + variables followed by arguments defining the sequence. +-Secondly, each generator except <code>:do</code> ++Secondly, each generator except <code>:do</code> + can handle an optional index variable. + This is most easily implemented using +-<a href="#:parallel"><code>:parallel</code></a> +-together with <a href="#:integers"><code>:integers</code></a>. ++<a href="#%3Aparallel"><code>:parallel</code></a> ++together with <a href="#%3Aintegers"><code>:integers</code></a>. + In case the payload generator needs an index anyhow +-(e.g. <a href="#:vector"><code>:vector</code></a>) ++(e.g. <a href="#%3Avector"><code>:vector</code></a>) + it is more efficient to add an index-variable if + none is given and to implement the indexed case. + Finally, make sure that no syntactic variable of the + generator pattern ever gets duplicated in the code + (to avoid exponential code size in nested application), +-and introduce sufficient intermediate variables to ++and introduce sufficient intermediate variables to + make sure expressions are evaluated at the correct time. +-</DD> +-</DL> +- +-<H1><a name="ext-examples"></a> +-Suggestions for application-specific extensions</H1> ++</p> ++</dd> ++</dl> + +-<H3>Arrays in the sense of <a href="#SRFI25">[SRFI25]</a></H3> ++<h2 id="ext-examples"> ++Suggestions for application-specific extensions</h2> + ++<h3>Arrays in the sense of <a href="#SRFI25">[SRFI25]</a></h3> ++<p> + In order to create an array from a sequence of elements, + a comprehension with the following syntax would be useful: +- ++</p> + <pre>(array-ec <shape> <qualifier>* <expression>).</pre> +- ++<p> + The comprehension constructs a new array of the given shape +-by filling it row-major with the sequence of elements as specified ++by filling it row-major with the sequence of elements as specified + by the qualifiers. +- ++</p> ++<p> + On the generator side, it would be most useful to have a + generator of the form +- ++</p> + <pre>(:array <vars> <arg>),</pre> +- ++<p> + running through the elements of the array in row-major. +-For the optional index variable, the extension ++For the optional index variable, the extension + <code>(index <k1> <k></code>*<code>)</code> + could be defined where <code><k1> <k></code>* + are variable names indexing the various dimensions. ++</p> + +- +-<H3>Random Numbers in the sense of <a href="#SRFI27">[SRFI27]</a></H3> +- ++<h3>Random Numbers in the sense of <a href="#SRFI27">[SRFI27]</a></h3> ++<p> + In order to create a vector or list of random numbers, + it would be convenient to have generators of the following form: +- ++</p> + <pre> + (:random-integer [ <range> [ <number> ] ] ) + (:random-real [ <number> ] )</pre> +- +-where <code><range></code> (default 2) indicates the range of ++<p> ++where <code><range></code> (default 2) indicates the range of + the integers and <code><number></code> (default infinity) + specifies how many elements are to be generated. + Derived from these basic generators, one could define several + other generators for other distributions (e.g. Gaussian). ++</p> + +- +-<H3>Bitstrings in the sense of <a href="#SRFI33">[SRFI33]</a></H3> +- ++<h3>Bitstrings in the sense of <a href="#SRFI33">[SRFI33]</a></h3> ++<p> + As eager comprehensions are efficient, they can be useful + for operations involving strings of bits. + It could be useful to have the following comprehension: +- ++</p> + <pre>(bitwise-ec <qualifier>* <expression>),</pre> +- ++<p> + which constructs an integer from bits obtained as values + of <code><expression></code> in the ordering defined + by <a href="#SRFI33">[SRFI33]</a>. +-In other words, if the sequence of values is +-<I>x</I>[0], <I>x</I>[1], ..., <I>x</I>[<I>n</I>-1] then +-the result is <I>x</I>[0] + <I>x</I>[1] 2 + ... + <I>x</I>[<I>n</I>-1] 2^(<I>n</I>-1). ++In other words, if the sequence of values is ++<i>x</i>[0], <i>x</i>[1], ..., <i>x</i>[<i>n</i>-1] then ++the result is <i>x</i>[0] + <i>x</i>[1] 2 + ... + <i>x</i>[<i>n</i>-1] 2^(<i>n</i>-1). + On the generator side, a generator of the form +- ++</p> + <pre>(:bitwise <vars> <arg1> <arg>*)</pre> +- ++<p> + runs through the sequence of bits obtained by appending the + binary digits of the integers <code><arg1> <arg></code>*. ++</p> ++<h3><a name="srfi40-ec"></a>Streams in the sense of <a href="#SRFI40">[SRFI 40]</a></h3> + +-<H3><a name="srfi40-ec"></a>Streams in the sense of <a href="#SRFI40">[SRFI 40]</a></H3> +- +-It is possible to 'lazify' the eager comprehension ++<p> ++It is possible to 'lazify' the eager comprehension + <a href="#list-ec"><code>list-ec</code></a>, + constructing a stream in the sense of <a href="#SRFI40">[SRFI 40]</a>. + Clearly, such a comprehension (<code>stream-ec</code>) + is not eager at all since it only runs the loops when results are requested. + It is also possible to define a <code>:stream</code>-generator with +-the same API as <a href="#:list"><code>:list</code></a> but running +-through streams instead of lists.<P> +- +-For what it is worth, +-the file <a href="http://srfi.schemers.org/srfi-42/srfi40-ec.scm">srfi40-ec.scm</a> implements ++the same API as <a href="#%3Alist"><code>:list</code></a> but running ++through streams instead of lists. ++</p> ++<p> ++For what it is worth, ++the file <a href="https://srfi.schemers.org/srfi-42/srfi40-ec.scm">srfi40-ec.scm</a> implements + <code>:stream</code> and <code>stream-ec</code> and gives an example. +-The implementation makes substantial use of ++The implementation makes substantial use of + <code>call-with-current-continuation</code> to run the loop + only when necessary. + In some implementations of Scheme this may involve + considerable overhead. ++</p> + +-<H3>Reading Text Files</H3> +- ++<h3>Reading Text Files</h3> ++<p> + Eager comprehensions can also be used to process files. + However, bear in mind that an eager comprehension wants + to read and process the entire file right away. + Nevertheless, these generators would be useful for + reading through the lines of a file or through the + characters of a file: +- ++</p> + <pre> + (:lines-of-file <vars> <file>) + (:chars-of-file <vars> [ (line <variable1>) ] [ (column <variable2>) ] <file>)</pre> +- ++<p> + Here <code><file></code> is either an input port + or a string interpreted as a filename. + In a similar fashion, generators reading from sockets defined + by URLs or other communication facilities could be defined. ++</p> + +-<H3>The Scheme shell <a href="#SCSH">Scsh</a></H3> +- ++<h3>The Scheme shell <a href="#SCSH">Scsh</a></h3> ++<p> + In the Scheme-shell Scsh it could be useful to have certain +-comprehensions and generators. ++comprehensions and generators. + Candidates for comprehensions are + <code>begin-ec</code>, + <code>|-ec</code>, + <code>||-ec</code>, and +-<code>&&-ec</code>. ++<code>&&-ec</code>. + Concerning generators, it might be useful to have +-<code>:directory</code> running through the +-records of a directory, and maybe a ++<code>:directory</code> running through the ++records of a directory, and maybe a + sophisticated <code>:file-match</code>-generator + could enumerate file record in a directory structure. + Optional variables of the generators could give +@@ -1409,18 +1465,18 @@ convenient access frequent components of the file records + (e.g. the filename). + Another candidate is <code>:env</code> to run through + the environment associations. +-It is left to other authors and other SRFIs to ++It is left to other authors and other SRFIs to + define a useful set of comprehensions and generators + for Scsh. ++</p> + ++<h2 id="design">Design Rationale</h2> + +-<H1><a name="design"></a>Design Rationale</H1> +- +-<H3>What is the difference between eager and lazy comprehensions?</H3> +- +-A lazy comprehension, for example <code>stream-of</code> in the ++<h3>What is the difference between eager and lazy comprehensions?</h3> ++<p> ++A lazy comprehension, for example <code>stream-of</code> in the + sense of <a href="#SRFI40">[SRFI 40]</a>, constructs an object +-representing a sequence of values. ++representing a sequence of values. + Only at the time these values are needed that they + are actually produced. + An eager comprehension, on the other hand, is an instruction to +@@ -1429,167 +1485,187 @@ for example as in <a href="#do-ec"><code>do-ec</code></a>. + In other words, it is nothing more sophisticated than a loop, + potentially with a more convenient notation. + This also explains why <code>stream-of</code> is the most +-fundamental <I>lazy</I> comprehension, and all others can ++fundamental <i>lazy</i> comprehension, and all others can + be formulated in terms of it, whereas the most fundamental +-<I>eager</I> comprehension is <code>do-ec</code>. +- +- +-<H3><a name="convention"></a>Why the [<I>outer</I> .. <I>inner</I> | <I>expr</I>] +-order of qualifiers?</H3> ++<i>eager</i> comprehension is <code>do-ec</code>. ++</p> + ++<h3 id="convention">Why the [<i>outer</i> .. <i>inner</i> | <i>expr</i>] ++order of qualifiers?</h3> ++<p> + In principle, there are six possible orders in which the + qualifiers and the expression of a comprehension can be written. + We denote the different conventions with a pattern in which +-<I>expr</I> denotes the expression over which the comprehension +-ranges, <I>inner</I> denotes the generator spinning fastest, and +-<I>outer</I> denotes the generator spinning slowest. +-For example, <a href="#Haskell">[Haskell]</a> and ++<i>expr</i> denotes the expression over which the comprehension ++ranges, <i>inner</i> denotes the generator spinning fastest, and ++<i>outer</i> denotes the generator spinning slowest. ++For example, <a href="#Haskell">[Haskell]</a> and + <a href="#Python">[Python]</a> use +-[<I>expr</I> | <I>outer</I> .. <I>inner</I>]. ++[<i>expr</i> | <i>outer</i> .. <i>inner</i>]. + (Probably with sufficient persistence, instances for any + of the conventions can be found on the Internet.) +-In addition, there is the common mathematical notation +-'{<I>f</I>(<I>x</I>) | <I>x</I> in <I>X</I>}'.<P> +- ++In addition, there is the common mathematical notation ++'{<i>f</i>(<i>x</i>) | <i>x</i> in <i>X</i>}'. ++</p> ++<p> + It is important to understand that the notational convention + does not only determine the order of enumeration but also the + scope of the variables introduced by the generators. +-The scope of <I>inner</I> includes <I>expr</I>, and the +-scope of <I>outer</I> should include <I>inner</I> to allow ++The scope of <i>inner</i> includes <i>expr</i>, and the ++scope of <i>outer</i> should include <i>inner</i> to allow + inner generates depending on outer generators. + Eventually, the choice for a particular syntactic convention is + largely a matter of personal preferences. + However, there are a few considerations that went into the +-choice made for this SRFI:<P> +- +-1. The mathematical notation is universally known and widely used. +-However, the mathematical notation denotes a <I>set</I> comprehension ++choice made for this SRFI: ++</p> ++<ol> ++ <li> ++ <p> ++The mathematical notation is universally known and widely used. ++However, the mathematical notation denotes a <i>set</i> comprehension + in which the order of the qualifiers is either irrelevant or must + be deduced from the context. +-For the purpose of eager comprehensions as a programming language ++For the purpose of eager comprehensions as a programming language + construct, the order does matter and a simple convention is a plus. + For these reasons, the mathematical notation as such is undesirable, + but its widespread use is in favor of +-[<I>expr</I> | <I>inner</I> .. <I>outer</I>] and +-[<I>expr</I> | <I>outer</I> .. <I>inner</I>].<P> +- +-2. It is desirable to have the scope of the variables increase ++[<i>expr</i> | <i>inner</i> .. <i>outer</i>] and ++[<i>expr</i> | <i>outer</i> .. <i>inner</i>]. ++ </p> ++ </li> ++ <li> ++ <p> ++It is desirable to have the scope of the variables increase + into one direction, as in +-[<I>expr</I> | <I>inner</I> .. <I>outer</I>] and +-[<I>outer</I> .. <I>inner</I> | <I>expr</I>], and ++[<i>expr</i> | <i>inner</i> .. <i>outer</i>] and ++[<i>outer</i> .. <i>inner</i> | <i>expr</i>], and + not change direction, as in +-[<I>expr</I> | <I>outer</I> .. <I>inner</I>] +-where <I>expr</I> is in the scope of <I>inner</I> +-but <I>outer</I> is not. ++[<i>expr</i> | <i>outer</i> .. <i>inner</i>] ++where <i>expr</i> is in the scope of <i>inner</i> ++but <i>outer</i> is not. + This is even more important if the syntax in Scheme +-does not explicitly contain the '|'-separator.<P> +- +-3. More complicated comprehensions with several nested generators ++does not explicitly contain the '|'-separator. ++ </p> ++ </li> ++ <li> ++ <p> ++More complicated comprehensions with several nested generators + eventually look like nested loops and Scheme always +-introduces them <I>outer</I> .. <I>inner</I> as in ++introduces them <i>outer</i> .. <i>inner</i> as in + <code>do</code> and named-<code>let</code>. +-This is in favor of +-[<I>expr</I> | <I>outer</I> .. <I>inner</I>] and +-[<I>outer</I> .. <I>inner</I> | <I>expr</I>]. ++This is in favor of ++[<i>expr</i> | <i>outer</i> .. <i>inner</i>] and ++[<i>outer</i> .. <i>inner</i> | <i>expr</i>]. + Shorter comprehension may look more naturally the +-other way around.<P> +- +-Regarding these contradicting preferences, I regard +-linearity in scoping (2.) most important, followed by ++other way around. ++ </p> ++ </li> ++</ol> ++<p> ++Regarding these contradicting preferences, I regard ++linearity in scoping (2.) most important, followed by + readability for more complicated comprehensions (3.). +-This leads to [<I>outer</I> .. <I>inner</I> | <I>expr</I>]. ++This leads to [<i>outer</i> .. <i>inner</i> | <i>expr</i>]. + An example in Scheme-syntax is + <code>(list-ec (: x 10) (: y x) (f x y))</code>, + which looks acceptable to me even without similarity + to the mathematical notation. + As a downside, the convention clashes with other the + convention used in other languages (e.g. Haskell and Python). ++</p> + +- +-<H3>You forgot [<I>choose your favorite here</I>]-ec!</H3> +- ++<h3>You forgot [<i>choose your favorite here</i>]-ec!</h3> ++<p> + I tried to construct a reasonably useful set of tools + according to what <a href="#R5RS">[R5RS]</a> specifies. + Nevertheless, is the choice what to include and what to +-leave out eventually a matter of personal preference.<P> +- ++leave out eventually a matter of personal preference.</p><p> ++</p> ++<p> + When 'packing the toolbox' I went for travelling light; + this SRFI does not include everything imaginable + or even everything useful. +-I oriented myself at the standard procedures ++I oriented myself at the standard procedures + of <a href="#R5RS">[R5RS]</a>, + with a few omissions and additions. +-A notable omission are <code>gcd-ec</code> and ++A notable omission are <code>gcd-ec</code> and + <code>lcm-ec</code> because they are one-liners, + and more severely, of questionable value in practice. + A notable addition are + <a href="#fold-ec"><code>fold-ec</code></a> and + <a href="#fold3-ec"><code>fold3-ec</code></a>, + providing a mechanism to define lots of useful one-liners. +-The other notable addition is ++The other notable addition is + <a href="#first-ec"><code>first-ec</code></a>, which + is the fundamental 'early stopping' comprehension. +-It is used to define +-<a href="#any?-ec"><code>any?-ec</code></a> and +-<a href="#every?-ec"><code>every?-ec</code></a> +-which are among the most frequent comprehensions.<P> +- ++It is used to define ++<a href="#any%3F-ec"><code>any?-ec</code></a> and ++<a href="#every%3F-ec"><code>every?-ec</code></a> ++which are among the most frequent comprehensions. ++</p> ++<p> + Concerning the generators, the same principle has been used. +-Additions include <a href="#:range"><code>:range</code></a> +-and friends because they are universally needed, and +-<a href="#:dispatched"><code>:dispatched</code></a> which is +-primarily intended for implementing <a href="#:"><code>:</code></a>. +- +- +-<H3><a name="dovetail"></a>Why is the order of enumeration specified?</H3> ++Additions include <a href="#%3Arange"><code>:range</code></a> ++and friends because they are universally needed, and ++<a href="#%3Adispatched"><code>:dispatched</code></a> which is ++primarily intended for implementing <a href="#%3A"><code>:</code></a>. ++</p> + ++<h3 id="dovetail">Why is the order of enumeration specified?</h3> ++<p> + For the purpose of this SRFI, every generator runs through +-its sequence of bindings in a well specified order, and nested +-generators run through the Cartesian product in the order ++its sequence of bindings in a well specified order, and nested ++generators run through the Cartesian product in the order + of nested loops. +-The purpose of this definition is making the sequence as ++The purpose of this definition is making the sequence as + easily predictable as possible. +- +-On the other hand, many mechanisms for <I>lazy</I> comprehensions ++</p> ++<p> ++On the other hand, many mechanisms for <i>lazy</i> comprehensions + do not specify the order in which the elements are enumerated. +-When it comes to infinite streams, this has the great advantage +-that a comprehension may interleave an inner and an outer ++When it comes to infinite streams, this has the great advantage ++that a comprehension may interleave an inner and an outer + enumeration, a method also known as 'dove-tailing' or 'diagonalizing'. +-Interleaving ensures that any value of the resulting stream is +-produced after a finite amount of time, even if one or more ++Interleaving ensures that any value of the resulting stream is ++produced after a finite amount of time, even if one or more + inner streams are infinite. ++</p> + +-<H3>Why both typed and dispatching generators?</H3> +- ++<h3>Why both typed and dispatching generators?</h3> ++<p> + The reason for typed generators is runtime efficiency. + In fact, the code produced by <code>:range</code> and others + will run as fast as a hand-coded <code>do</code>-loop. + The primary purpose of the dispatching generator is convenience. + It comes at the price of reduced runtime performance, + both for loop iteration and startup. ++</p> + +-<H3>Why the <I>something</I><code>-ec</code> and <code>:</code><I>type</I> naming?</H3> +- +-The purpose of the <code>:</code><I>type</I> convention is to keep ++<h3>Why the <i>something</i><code>-ec</code> and <code>:</code><i>type</i> naming?</h3> ++<p> ++The purpose of the <code>:</code><i>type</i> convention is to keep + many common comprehensions down to one-liners. + In my opinion, the fundamental nature of eager comprehensions + justifies a single character naming convention. +-The <I>something</I><code>-ec</code> convention is primarily intended to +-stay away from the widely used <I>something</I><code>-of</code>. ++The <i>something</i><code>-ec</code> convention is primarily intended to ++stay away from the widely used <i>something</i><code>-of</code>. + It reduces confusion and conflict with related mechanisms. ++</p> + +-<H3>Why combine variable binding and sequence definition?</H3> +- ++<h3>Why combine variable binding and sequence definition?</h3> ++<p> + The generators of this SRFI do two different things with + a single syntactic construct: They define a sequence of values + to enumerate and they specify a variable (within a certain + scope) to run through that sequence. +-An alternative is to separate the two, for example as it +-has been done in +-<a href="http://srfi.schemers.org/srfi-40/srfi-40.html">SRFI 40</a>.<P> +- ++An alternative is to separate the two, for example as it ++has been done in ++<a href="srfi-40.html">SRFI 40</a>. ++</p> ++<p> + The reason for combining sequence definition and enumeration +-for the purpose of this SRFI is threefold. ++for the purpose of this SRFI is threefold. + Firstly, sequences of values are not explicitly represented as + objects in the typed generators; the generators merely + manipulate an internal state. +@@ -1598,115 +1674,125 @@ common comprehensions and reduces syntax to the naked minimum. + Thirdly, this SRFI aims at the highest possible performance for + typed generators, which is achieved if the state being manipulated + is represented by the loop variable itself. ++</p> + +-<H3>Why is <code>(: <vars>)</code> illegal?</H3> +- +-It is reasonable and easy to define <code>(<a href="#:">:</a> <vars>)</code> +-as <code>(<a href="#:integers">:integers</a> <vars>)</code>, ++<h3>Why is <code>(: <vars>)</code> illegal?</h3> ++<p> ++It is reasonable and easy to define <code>(<a href="#%3A">:</a> <vars>)</code> ++as <code>(<a href="#%3Aintegers">:integers</a> <vars>)</code>, + enumerating the non-negative integers. + However, it turned out that a frequent mistake in using the + eager comprehensions is to forget either the variable + or an argument for the enumeration. +-As this would lead to an infinite loop (not always ++As this would lead to an infinite loop (not always + equally pleasant in interactive sessions), it is not allowed. ++</p> + +-<H3>Why is there no <code>:sequential</code>?</H3> +- +-Just like <a href="#:parallel"><code>:parallel</code></a> ++<h3>Why is there no <code>:sequential</code>?</h3> ++<p> ++Just like <a href="#%3Aparallel"><code>:parallel</code></a> + enumerates generators in + parallel, a <code>:sequential</code> generator could +-enumerate a concatenation of several generator, starting ++enumerate a concatenation of several generator, starting + the next one when the previous has finished. + The reason for not having such a qualifier is + that the generators should use all the same variable name + and there is no hygienic and referentially transparent + way of enforcing this (or even knowing the variable). ++</p> + +-<H3>Why is there no general <code>let</code>-qualifier?</H3> +- +-It is easy to add <code>let</code>, <code>let*</code>, ++<h3>Why is there no general <code>let</code>-qualifier?</h3> ++<p> ++It is easy to add <code>let</code>, <code>let*</code>, + and <code>letrec</code> as cases to <code><qualifier></code>. +-This would allow more sophisticated local variables +-and expressions than possible with +-<code>(<a href="#:let">:let</a> <vars> <expression>)</code> and ++This would allow more sophisticated local variables ++and expressions than possible with ++<code>(<a href="#%3Alet">:let</a> <vars> <expression>)</code> and + <code>(<a href="#begin">begin</a> <sequence></code>*<code>)</code>. + In particular, a local <code><definition></code> + in the sense of <a href="#R5RS">[R5RS, 7.1.5.]</a> would +-be possible.<P> +- +-There are two reasons for not including <code>let</code> ++be possible. ++</p> ++<p> ++There are two reasons for not including <code>let</code> + and friends as qualifiers. + The first reason concerns readability. +-A qualifier of the form ++A qualifier of the form + <code>(let (<binding spec></code>*<code>) <body>)</code> +-only makes sense if the scope of the new variables ends at the +-end of the comprehension, and <I>not</I> already ++only makes sense if the scope of the new variables ends at the ++end of the comprehension, and <i>not</i> already + after <code><body></code>. +-The similarity with ordinary <code>let</code>-expressions ++The similarity with ordinary <code>let</code>-expressions + would be very confusing. + The second reason concerns the design rationale. + If sophisticated <code>let</code>-qualifiers involving +-recursion or local definitions are needed, it is likely ++recursion or local definitions are needed, it is likely + that eager comprehensions are being overused. + In that case it might be better to define a procedure + for the task. + So including an invitation to overuse the mechanism would +-be a serious violation of the +-<I>Keep It Simple and Stupid</I> principle. +- +-<H3>Why is there no <code>:nested</code> generator?</H3> ++be a serious violation of the ++<i>Keep It Simple and Stupid</i> principle. ++</p> + ++<h3>Why is there no <code>:nested</code> generator?</h3> ++<p> + The specification above defines <a href="#nested"><code>nested</code></a> +-as a qualifier but <a href="#:parallel"><code>:parallel</code></a> ++as a qualifier but <a href="#%3Aparallel"><code>:parallel</code></a> + as a generator. + In particular, this makes it impossible to make parallel +-generators from nested ones.<P> +- ++generators from nested ones. ++</p> ++<p> + This design simply reflects an implementability limitation. + All component generators of <code>:parallel</code> are +-transformed into <a href="#:do"><code>:do</code></a>-generators +-and these can be merged into a parallel generator. ++transformed into <a href="#%3Ado"><code>:do</code></a>-generators ++and these can be merged into a parallel generator. + However, nested generators cannot be merged easily without +-losing the type of the generator, ++losing the type of the generator, + which would seriously hurt modularity and performance. ++</p> + +-<H3>Is <code>any?-ec</code> eager?</H3> +- +-Yes, it is still eager because it immediately starts to +-run through the sequence.<P> +- +-In fact, the reference implementation makes sure ++<h3>Is <code>any?-ec</code> eager?</h3> ++<p> ++Yes, it is still eager because it immediately starts to ++run through the sequence. ++</p> ++<p> ++In fact, the reference implementation makes sure + <a href="#first-ec"><code>first-ec</code></a>, +-<a href="#any?-ec"><code>any?-ec</code></a>, and +-<a href="#every?-ec"><code>every?-ec</code></a> +-execute efficiently so they can be used conveniently +-as in ++<a href="#any%3F-ec"><code>any?-ec</code></a>, and ++<a href="#every%3F-ec"><code>every?-ec</code></a> ++execute efficiently so they can be used conveniently ++as in + <code>(every?-ec (:list x my-list) (pred? x))</code>. ++</p> + +-<H3>Why this whole <code>:dispatched</code> business?</H3> +- +-It is specified above that <I>the</I> dispatching generator, +-called <a href="#:"><code>:</code></a>, is just a special case +-of <a href="#:dispatched"><code>:dispatched</code></a> using ++<h3>Why this whole <code>:dispatched</code> business?</h3> ++<p> ++It is specified above that <i>the</i> dispatching generator, ++called <a href="#%3A"><code>:</code></a>, is just a special case ++of <a href="#%3Adispatched"><code>:dispatched</code></a> using + a global dispatching procedure. + Alternatively, a simple fixed global mechanism to extend +-<a href="#:"><code>:</code></a> could have been used. ++<a href="#%3A"><code>:</code></a> could have been used. + This is much simpler but does not support the definition +-of new dispatched generators.<P> +- +-The purpose of <a href="#:dispatched"><code>:dispatched</code></a> ++of new dispatched generators. ++</p> ++<p> ++The purpose of <a href="#%3Adispatched"><code>:dispatched</code></a> + and its utilities +-(<a href="#:generator-proc"><code>:generator-proc</code></a> and ++(<a href="#%3Agenerator-proc"><code>:generator-proc</code></a> and + <a href="#dispatch-union"><code>dispatch-union</code></a>) + is the following. +-Assume <a href="#:"><code>:</code></a> is to be used inside a ++Assume <a href="#%3A"><code>:</code></a> is to be used inside a + module but it is essential that no other module can spoil it, + e.g. by installing a very slow dispatcher. + The recommended way to proceed in this case is to define a +-local copy of the original dispatching generator +-<a href="#:"><code>:</code></a>, ++local copy of the original dispatching generator ++<a href="#%3A"><code>:</code></a>, + for example with the following code +- ++</p> + <pre> + (define :my-dispatch + (make-initial-:-dispatch) ) +@@ -1717,33 +1803,36 @@ for example with the following code + (:dispatched cc var (index i) :my-dispatch arg1 arg ...) ) + ((:my cc var arg1 arg ...) + (:dispatched cc var :my-dispatch arg1 arg ...) ))),</pre> +- ++<p> + and to use the new generator <code>:my</code> instead of +-<a href="#:"><code>:</code></a>.<P> +- ++<a href="#%3A"><code>:</code></a>. ++</p> ++<p> + An alternative for the dispatching mechanism as defined in + this SRFI is the use of parameter objects in the sense of +-<a href="#SRFI39">[SRFI 39]</a>. ++<a href="#SRFI39">[SRFI 39]</a>. + The dispatching generator would then access a dynamically + scoped variable to find the dispatcher, allowing full + control over dispatching. + However, this approach does not solve the dilemma that it is +-sometimes useful that <a href="#:"><code>:</code></a> is global ++sometimes useful that <a href="#%3A"><code>:</code></a> is global + and sometimes undesired. + The approach specified for this SRFI addresses this dilemma +-by offering options.<P> +- ++by offering options. ++</p> ++<p> + Another alternative for dealing with the dispatching + problem is adding an optional argument to the syntax of +-<a href="#:"><code>:</code></a> through which the dispatcher ++<a href="#%3A"><code>:</code></a> through which the dispatcher + can be passed explicitly. +-However, as <a href="#:"><code>:</code></a> has variable ++However, as <a href="#%3A"><code>:</code></a> has variable + arity and the identifier for the variable cannot be +-distinguished from any value for a dispatcher, ++distinguished from any value for a dispatcher, + this is syntactically problematic. ++</p> + +-<H3>Why is there no local mechanism for adding to <a href="#:"><code>:</code></a>?</H3> +- ++<h3>Why is there no local mechanism for adding to <a href="#%3A"><code>:</code></a>?</h3> ++<p> + According to <a href="#R5RS">[R5RS, 7.1.6.]</a> macros can only + be defined at the level of the <code><program></code> syntax. + This implies that the scope of typed generators cannot easily be +@@ -1751,17 +1840,19 @@ limited to local scopes. + As typed and dispatched generators go together, + there is also no strong need for a limited scope + of dispatched generators either. +-Furthermore, locally extendable dispatchers are another major ++Furthermore, locally extendable dispatchers are another major + headache to those trying to understand other people's code. ++</p> + +-<H3>Why are dispatchers unary?</H3> +- +-As defined in <a href="#:dispatched"><code>:dispatched</code></a>, ++<h3>Why are dispatchers unary?</h3> ++<p> ++As defined in <a href="#%3Adispatched"><code>:dispatched</code></a>, + a dispatching procedure is called with a single argument being +-the list of values to dispatch on. ++the list of values to dispatch on. + An alternative is to <code>apply</code> the dispatcher to the +-list of values to dispatch on, which would be more natural in Scheme.<P> +- ++list of values to dispatch on, which would be more natural in Scheme. ++</p> ++<p> + The reason for not using <code>apply</code> is a minor + improvement in efficiency. + Every time <code>apply</code> is used on a procedure of variable +@@ -1769,55 +1860,61 @@ arity, an object containing the argument list is allocated on + the heap. + As a dispatcher may call many other dispatchers, this will adds + to the overhead of dispatching, which is relevant in inner loops. ++</p> + +-<H3>Why are there two fold comprehensions?</H3> +- +-The reason for having two fold comprehensions ++<h3>Why are there two fold comprehensions?</h3> ++<p> ++The reason for having two fold comprehensions + (<a href="#fold-ec"><code>fold-ec</code></a> and +-<a href="#fold3-ec"><code>fold3-ec</code></a>) is efficiency.<P> +- +-Clearly, the more general construction is +-<a href="#fold3-ec"><code>fold3-ec</code></a> ++<a href="#fold3-ec"><code>fold3-ec</code></a>) is efficiency. ++</p> ++<p> ++Clearly, the more general construction is ++<a href="#fold3-ec"><code>fold3-ec</code></a> + as it allows individual treatment of the empty + sequence case and the singleton sequence case. + However, this comes at the price of more book-keeping +-as can be seen from the ++as can be seen from the + <a href="#fold3-ec-example">implementation example</a>. + As the overhead is located within inner loops, + it makes sense to define another fold comprehension + for the case where the added flexibility is not needed. +-This is <a href="#fold-ec"><code>fold-ec</code></a>.<P> +- ++This is <a href="#fold-ec"><code>fold-ec</code></a>. ++</p> ++<p> + The names <code>fold-ec</code> and <code>fold3-ec</code> + have been chosen for the comprehensions in order to stay + clear any other 'fold' that may be around. ++</p> + +-<H3>Why is <code>:char-range</code> not defined by <code>integer->char</code>?</H3> +- +-The definition of <a href="#:char-range"><code>:char-range</code></a> ++<h3>Why is <code>:char-range</code> not defined by <code>integer->char</code>?</h3> ++<p> ++The definition of <a href="#%3Achar-range"><code>:char-range</code></a> + specifies a sequence of adjacent characters ordered by <code>char<=?</code>. +-The reason for not using <code>char->integer</code> and +-<code>integer->char</code> is the fact that ++The reason for not using <code>char->integer</code> and ++<code>integer->char</code> is the fact that + <a href="#R5RS">[R5RS, 6.3.4.]</a> leaves it to the implementation + whether the integers representing characters are consecutive or not. + In effect, this underspecification is inherited by <code>:char-range</code>. ++</p> + +- +-<H1><a name="related-work"></a>Related Work and Acknowledgements</H1> +- ++<h2 id="related-work">Related Work and Acknowledgements</h2> ++<p> + Several other proposals related to the mechanism specified here exists. +-The following mechanisms are made for and in Scheme (or at least a +-specific dialect thereof):<P> +- ++The following mechanisms are made for and in Scheme (or at least a ++specific dialect thereof): ++</p> ++<p> + First of all, the report <a href="#R5RS">[R5RS]</a> of Scheme itself +-defines two constructs for writing loops: <code>do</code> and ++defines two constructs for writing loops: <code>do</code> and + named-<code>let</code>. +-Both constructs express a single loop (not nested), ++Both constructs express a single loop (not nested), + possibly with several variables running in parallel, +-based on explicit manipulation of the state variables. ++based on explicit manipulation of the state variables. + For example <code>(do ((x 0 (+ x 1))) ((= x 10)) (display x))</code> +-explicitly mentions how to obtain the next binding of <code>x</code>.<P> +- ++explicitly mentions how to obtain the next binding of <code>x</code>. ++</p> ++<p> + Richard Kelsey's "Macros for writing loops", <a href="#MWL">[MWL]</a> + are an extension to Scheme48 to simplify the formulation of loops. + The basic idea is to stick with a <code>do</code>-like syntax for +@@ -1826,9 +1923,9 @@ a state variable explicitly. + For example, <code>(list* x '(1 2 3))</code> expresses an enumeration + of the variable <code>x</code> through the list <code>(1 2 3)</code> + without explicit state manipulation. +-The iteration constructs of <a href="#MWL">[MWL]</a>, named ++The iteration constructs of <a href="#MWL">[MWL]</a>, named + <code>iterate</code> and <code>reduce</code>, +-express a single (not nested) loop (<code>iterate</code>) or ++express a single (not nested) loop (<code>iterate</code>) or + comprehension (<code>reduce</code>) with any number of + parallel enumerations. + A most important feature of the <a href="#MWL">[MWL]</a>-concept +@@ -1837,10 +1934,11 @@ In effect, the addition of a new sequence type does not + require a modification of the existing macros. + This is achieved by carefully limiting the expressive + power of the loop constructs and by using the macros +-in <I>Continuation Passing Style</I> to call other macros. +-The <a href="#MWL">[MWL]</a>-concept, and its implementation, +-were most influential for this SRFI.<P> +- ++in <i>Continuation Passing Style</i> to call other macros. ++The <a href="#MWL">[MWL]</a>-concept, and its implementation, ++were most influential for this SRFI. ++</p> ++<p> + Another related mechanism is the library of streams recently + submitted by Phil L. Bewig as <a href="#SRFI40">[SRFI 40]</a>. + The library contains a data type to represent even +@@ -1856,35 +1954,36 @@ Nevertheless, modularity is high since it is easy to define + a procedure producing a stream object and this can be + used for enumeration. + The order of enumeration is left unspecified to allow +-interleaving of generators (also refer to ++interleaving of generators (also refer to + <a href="#dovetail">above</a>.) + Before Phil submitted his SRFIs, we had a short + discussion in which we clarified the semantic and syntactic + differences of our approaches. +-It turned out that the mechanisms are sufficiently ++It turned out that the mechanisms are sufficiently + different not to unify them. + The most important difference is the design rationale: + Phil created his library to support the stream-paradigm +-in Scheme, inspired by the work done for Haskell and ++in Scheme, inspired by the work done for Haskell and + other lazy languages, and intrigued by the beauty + of programming with infinite streams. +-My work only aims at a convenient way of expressing ++My work only aims at a convenient way of expressing + frequent patterns of loops in a compact way. + For what it is worth, section <a href="#srfi40-ec">SRFI40-ec</a> + contains a suggestion for extending the eager comprehension +-mechanism for SRFI40-streams.<P> +- ++mechanism for SRFI40-streams. ++</p> ++<p> + Phil's work on streams and lazy comprehensions in Scheme + triggered Eli Barzilay to implement a library of eager + comprehensions for PLT-Scheme, <a href="#Eli">[Eli]</a>. + The mechanism implemented by Eli is in essence very + similar to the one proposed in this SRFI, and the two + efforts have been independent until recently. +-Syntactically, Eli uses infix operators for generators, +-whereas this SRFI is purely prefix, and Eli uses the +-[<I>expr</I> | <I>outer</I> .. <I>inner</I>] convention ++Syntactically, Eli uses infix operators for generators, ++whereas this SRFI is purely prefix, and Eli uses the ++[<i>expr</i> | <i>outer</i> .. <i>inner</i>] convention + for nesting, whereas this SRFI uses the +-[<I>outer</I> .. <I>inner</I> | <I>expr</I>] ++[<i>outer</i> .. <i>inner</i> | <i>expr</i>] + <a href="#convention">convention</a>. + Semantically, Eli's mechanism defines more flexible + loops than this SRFI. +@@ -1892,208 +1991,214 @@ Comprehensions are regarded as generalized collection + processes like fold and reduce. + The mechanism in this SRFI is more restricted with respect + to control flow (there is no general <code>while</code>) +-and more extensive with respect to generators and ++and more extensive with respect to generators and + comprehensions. +-Despite the strong conceptual similarity, the design ++Despite the strong conceptual similarity, the design + rationales are different. + This SRFI focuses on portability and modular extension, +-whatever that may cost in terms of expressive power.<P> +- +-Finally, I would like to thank Mike Sperber for his ++whatever that may cost in terms of expressive power. ++</p> ++<p> ++Finally, I would like to thank Mike Sperber for his + encouragement to proceed with the SRFI and for several + discussions of the matter. + In particular, the dispatching mechanism evolved + rapidly during discussions with Mike. ++</p> + +- +-<H1><a name="refimpl"></a>Implementation</H1> +- +-The reference implementation focuses on portability, ++<h2 id="refimpl">Implementation</h2> ++<p> ++The reference implementation focuses on portability, + performance, readability and simplicity, roughly in this order. +-It is written in <a href="#R5RS">[R5RS]</a>-Scheme ++It is written in <a href="#R5RS">[R5RS]</a>-Scheme + (including macros) extended by <a href="#SRFI23">[SRFI 23]</a> + (<code>error</code>). + The reference implementation was developed + under <a href="#Scheme48">Scheme48</a> (0.57), + <a href="#PLT">PLT</a> (202, 204), and +-<a href="#SCM">SCM</a> (5d7).<P> +- +-The file <a href="http://srfi.schemers.org/srfi-42/ec.scm">ec.scm</a> is the source of ++<a href="#SCM">SCM</a> (5d7). ++</p> ++<p> ++The file <a href="https://srfi.schemers.org/srfi-42/ec.scm">ec.scm</a> is the source of + the reference implementation. + It also contains comments concerning potential problems. +-Implementors might find the file <a href="http://srfi.schemers.org/srfi-42/design.scm">design.scm</a> +-helpful. +-It contains alternative implementations of certain comprehensions ++Implementors might find the file <a href="https://srfi.schemers.org/srfi-42/design.scm">design.scm</a> ++helpful. ++It contains alternative implementations of certain comprehensions + and generators in order to simplify tuning the implementation +-of this SRFI for different Scheme systems.<P> +- +-The file <a href="http://srfi.schemers.org/srfi-42/examples.scm">examples.scm</a> contains a ++of this SRFI for different Scheme systems. ++</p> ++<p> ++The file <a href="https://srfi.schemers.org/srfi-42/examples.scm">examples.scm</a> contains a + collection of examples, and some code checking their results. + The purpose of most examples is detecting implementation errors, + but the section 'Less artificial examples' contains a few +-real-world examples. <P> +- +-The file <a href="http://srfi.schemers.org/srfi-42/timing.scm">timing.scm</a> contains some ++real-world examples. ++</p> ++<p> ++The file <a href="https://srfi.schemers.org/srfi-42/timing.scm">timing.scm</a> contains some + code to measure an idea of performance of the comprehensions. + A hand-coded <code>do</code>-loop, the typed generator +-<code>(<a href="#:range">:range</a> </code><I>n</I><code>)</code>, +-and the dispatching generator +-<code>(<a href="#:">:</a> </code><I>n</I><code>)</code> ++<code>(<a href="#%3Arange">:range</a> </code><i>n</i><code>)</code>, ++and the dispatching generator ++<code>(<a href="#%3A">:</a> </code><i>n</i><code>)</code> + are compared. + For each loop we compare the time needed + per iteration and the time needed to construct the loop (the startup delay). +-As a rule of thumb, <code>:range</code> is as fast (or slightly faster) +-as a hand-coded <code>do</code>-loop per iteration and needs about a ++As a rule of thumb, <code>:range</code> is as fast (or slightly faster) ++as a hand-coded <code>do</code>-loop per iteration and needs about a + third more time for startup (due to type checking of the argument). + The dispatching generator needs about twice the time per iteration + (due to calling the generator procedure) and needs about five times +-as long for startup (due to dispatching).<P> +- +-The file <a href="http://srfi.schemers.org/srfi-42/extension.scm">extension.scm</a> contains +-examples for adding new generators and comprehensions.<P> ++as long for startup (due to dispatching). ++</p> ++<p> ++The file <a href="https://srfi.schemers.org/srfi-42/extension.scm">extension.scm</a> contains ++examples for adding new generators and comprehensions. ++</p> + +-<H1>References</H1> ++<h2>References</h2> + +-<TABLE> ++<table> + +-<TR> +-<TD><a name="R5RS">[R5RS]</a> +-<TD>Richard Kelsey, William Clinger, and Jonathan Rees (eds.): ++<tr> ++<td><a name="R5RS">[R5RS]</a> ++</td><td>Richard Kelsey, William Clinger, and Jonathan Rees (eds.): + Revised(5) Report on the Algorithmic Language Scheme of + 20 February 1998. + Higher-Order and Symbolic Computation, Vol. 11, No. 1, September 1998. + <a href="http://schemers.org/Documents/Standards/R5RS/"> + http://schemers.org/Documents/Standards/R5RS/</a>. +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="MWL">[MWL]</a> +-<TD>Richard Kelsey, Jonathan Rees: ++<tr> ++<td><a name="MWL">[MWL]</a> ++</td><td>Richard Kelsey, Jonathan Rees: + The Incomplete Scheme48 Reference Manual for Release 0.57 (July 15, 2001). + Section "Macros for writing loops". + <a href="http://s48.org/0.57/manual/s48manual_49.html">http://s48.org/0.57/manual/s48manual_49.html</a> +-</TR> +- +- +-<TR> +-<TD><a name="SRFI1">[SRFI 1]</a> +-<TD>Olin Shivers: List Library. +-<a href="http://srfi.schemers.org/srfi-1/">http://srfi.schemers.org/srfi-1/</a> +-</TR> +- +-<TR> +-<TD><a name="SRFI23">[SRFI 23]</a> +-<TD>Stephan Houben: Error reporting mechanism +-<a href="http://srfi.schemers.org/srfi-23/">http://srfi.schemers.org/srfi-23/</a> +-</TR> +- +- +-<TR> +-<TD><a name="SRFI25">[SRFI 25]</a> +-<TD>Jussi Piitulainen: Multi-dimensional Array Primitives. +-<a href="http://srfi.schemers.org/srfi-25/">http://srfi.schemers.org/srfi-25/</a> +-</TR> +- +-<TR> +-<TD><a name="SRFI27">[SRFI 27]</a> +-<TD>Sebastian Egner: Sources of Random Bits. +-<a href="http://srfi.schemers.org/srfi-27/">http://srfi.schemers.org/srfi-27/</a> +-</TR> +- +-<TR> +-<TD><a name="SRFI33">[SRFI 33]</a> +-<TD>Olin Shivers: Integer Bitwise-operation Library. +-<a href="http://srfi.schemers.org/srfi-33/">http://srfi.schemers.org/srfi-33/</a> +-</TR> +- +-<TR> +-<TD><a name="SRFI39">[SRFI 39]</a> +-<TD>Marc Feeley: Parameter objects. +-<a href="http://srfi.schemers.org/srfi-39/">http://srfi.schemers.org/srfi-39/</a> +-</TR> +- +-<TR> +-<TD><a name="SRFI40">[SRFI 40]</a> +-<TD>Philip L. Bewig: A Library of Streams. +-<a href="http://srfi.schemers.org/srfi-40/">http://srfi.schemers.org/srfi-40/</a> +-</TR> +- +-<TR> +-<TD><a name="Eli">[Eli]</a> +-<TD>Eli Barzilay: Documentation for "misc.ss". 2002. ++</td></tr> ++ ++ ++<tr> ++<td><a name="SRFI1">[SRFI 1]</a> ++</td><td>Olin Shivers: List Library. ++<a href="srfi-1.html">http://srfi.schemers.org/srfi-1/</a> ++</td></tr> ++ ++<tr> ++<td><a name="SRFI23">[SRFI 23]</a> ++</td><td>Stephan Houben: Error reporting mechanism ++<a href="srfi-23.html">http://srfi.schemers.org/srfi-23/</a> ++</td></tr> ++ ++ ++<tr> ++<td><a name="SRFI25">[SRFI 25]</a> ++</td><td>Jussi Piitulainen: Multi-dimensional Array Primitives. ++<a href="srfi-25.html">http://srfi.schemers.org/srfi-25/</a> ++</td></tr> ++ ++<tr> ++<td><a name="SRFI27">[SRFI 27]</a> ++</td><td>Sebastian Egner: Sources of Random Bits. ++<a href="srfi-27.html">http://srfi.schemers.org/srfi-27/</a> ++</td></tr> ++ ++<tr> ++<td><a name="SRFI33">[SRFI 33]</a> ++</td><td>Olin Shivers: Integer Bitwise-operation Library. ++<a href="https://srfi.schemers.org/srfi-33/">http://srfi.schemers.org/srfi-33/</a> ++</td></tr> ++ ++<tr> ++<td><a name="SRFI39">[SRFI 39]</a> ++</td><td>Marc Feeley: Parameter objects. ++<a href="srfi-39.html">http://srfi.schemers.org/srfi-39/</a> ++</td></tr> ++ ++<tr> ++<td><a name="SRFI40">[SRFI 40]</a> ++</td><td>Philip L. Bewig: A Library of Streams. ++<a href="srfi-40.html">http://srfi.schemers.org/srfi-40/</a> ++</td></tr> ++ ++<tr> ++<td><a name="Eli">[Eli]</a> ++</td><td>Eli Barzilay: Documentation for "misc.ss". 2002. + <a href="http://www.cs.cornell.edu/eli/Swindle/misc-doc.html#collect">http://www.cs.cornell.edu/eli/Swindle/misc-doc.html#collect</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name=Folds>[Folds]</a> +-<TD>John David Stone: Folds and reductions. ++<tr> ++<td><a name="Folds">[Folds]</a> ++</td><td>John David Stone: Folds and reductions. + Posting in relation to <a href="#SRFI1">[SRFI 1]</a> on 8-Jan-1999. +-<a href="http://srfi.schemers.org/srfi-1/mail-archive/msg00021.html">http://srfi.schemers.org/srfi-1/mail-archive/msg00021.html</a> +-</TR> ++<a href="https://srfi.schemers.org/srfi-1/mail-archive/msg00021.html">http://srfi.schemers.org/srfi-1/mail-archive/msg00021.html</a> ++</td></tr> + +-<TR> +-<TD><a name="Haskell">[Haskell]</a> +-<TD>Simon L. Peyton Jones, John Hughes: The Haskell 98 Report 1 February 1999. ++<tr> ++<td><a name="Haskell">[Haskell]</a> ++</td><td>Simon L. Peyton Jones, John Hughes: The Haskell 98 Report 1 February 1999. + Section 3.11 "List Comprehensions". + <a href="http://www.haskell.org/onlinereport/exps.html#sect3.11">http://www.haskell.org/onlinereport/exps.html#sect3.11</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="Python">[Python]</a> +-<TD>Guido van Rossum, Fred L. Drake Jr. (eds.): ++<tr> ++<td><a name="Python">[Python]</a> ++</td><td>Guido van Rossum, Fred L. Drake Jr. (eds.): + Python Reference Manual. + Section 5.2.4 "List displays". + Release 2.2, December 21, 2001. + <a href="http://python.org/doc/2.2/ref/lists.html">http://python.org/doc/2.2/ref/lists.html</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="SICP">[SICP]</a> +-<TD>Harold Abelson, Gerald J. Sussman, Julie Sussman: ++<tr> ++<td><a name="SICP">[SICP]</a> ++</td><td>Harold Abelson, Gerald J. Sussman, Julie Sussman: + Structure and Interpretation of Computer Programs. + MIT Press, 1985. + <a href="http://mitpress.mit.edu/sicp/">http://mitpress.mit.edu/sicp/</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="IFPL">[IFPL]</a> +-<TD>Philip Wadler: List Comprehensions (Chapter 7). In: ++<tr> ++<td><a name="IFPL">[IFPL]</a> ++</td><td>Philip Wadler: List Comprehensions (Chapter 7). In: + Simon L. Peyton Jones: The Implementation of Functional Programming Languages. + Prentice Hall, 1987. +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="Scheme48">[Scheme48]</a> +-<TD>Richard Kelsey, Jonathan Rees: Scheme48 Release 0.57 (July 15, 2001). ++<tr> ++<td><a name="Scheme48">[Scheme48]</a> ++</td><td>Richard Kelsey, Jonathan Rees: Scheme48 Release 0.57 (July 15, 2001). + <a href="http://s48.org/">http://s48.org/</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="SCM">[SCM]</a> +-<TD>Aubrey Jaffer: SCM Scheme Implementation. Version 5d7 (November 27, 2002). ++<tr> ++<td><a name="SCM">[SCM]</a> ++</td><td>Aubrey Jaffer: SCM Scheme Implementation. Version 5d7 (November 27, 2002). + <a href="http://www.swiss.ai.mit.edu/~jaffer/SCM.html">http://www.swiss.ai.mit.edu/~jaffer/SCM.html</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="PLT">[PLT]</a> +-<TD>PLT People: PLT Scheme, DrScheme Version 203. ++<tr> ++<td><a name="PLT">[PLT]</a> ++</td><td>PLT People: PLT Scheme, DrScheme Version 203. + <a href="http://www.plt-scheme.org/">http://www.plt-scheme.org/</a> +-</TR> ++</td></tr> + +-<TR> +-<TD><a name="SCSH">[Scsh]</a> +-<TD>Olin Shivers, Brian D. Carlstrom, Martin Gasbichler, Mike Sperber: ++<tr> ++<td><a name="SCSH">[Scsh]</a> ++</td><td>Olin Shivers, Brian D. Carlstrom, Martin Gasbichler, Mike Sperber: + Scsh Reference Manual. + For scsh release 0.6.3. + <a href="http://scsh.net/">http://scsh.net/</a> +-</TR> ++</td></tr> + + +-</TABLE> ++</table> + + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Sebastian Egner (2003). All Rights Reserved.</p> + + <p> +@@ -2120,12 +2225,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <hr> ++ <hr /> + <address>Author: <a href="mailto:sebastian.egner@philips.com">Sebastian Egner</a></address> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Francisco Solsona</a></address> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + <!-- Created: Tue Feb 4 13:21:00 MST 2003 --> + <!-- hhmts start --> +-Last modified: Tue Apr 5 10:43:00 CEST 2005 ++Last modified: Sun Jan 28 13:40:34 MET 2007 + <!-- hhmts end --> + + </body> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html +index 7ca1cd3..8c12b5a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-43.html +@@ -1,34 +1,30 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" +- "http://www.w3.org/TR/html4/loose.dtd"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-43 ┃ ++┃ Commit: b461b58343274164e837d47a73f8755a92920b5c ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <!-- Non-indentation necessary for the commit check junk. --> +-<title>SRFI 43: Vector Library</title> +- <meta http-equiv="Content-type" +- content="text/html; charset=iso-8859-1"> ++ <title>SRFI 43: Vector Library</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + <style type="text/css"> + /* <![CDATA[ */ +- body { +- padding-right: 5%; +- } +- +- h2 { +- padding-left: 6%; +- } +- +- /* Ugly hack to make the header work right */ +- h1.nonheader { +- padding-left: 8.5%; +- } +- +- h1 { +- margin-left: -4.5%; +- } +- +- div.header { +- padding-left: 8%; +- } +- + p, dl, code.indented { + padding-left: 8%; + } +@@ -81,36 +77,29 @@ + </head> + <body> + +- <div class="header"> +-<!-- +- Special SRFI header, formatted oddly due to the commit check script +- for SRFI CVS. +- --> +-<H1>Title</H1> +-Vector library +- +-<H1>Author</H1> +-Taylor Campbell +- +-<H1>Status</H1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail-archive/maillist.html">the archive of the mailing list</A>. +-<UL> +-<LI>Received: 2003/03/26 +-<LI>Draft: 2003/04/03-2003/06/01 +-<LI>Revised: 2003/07/15 +-<LI>Revised: 2003/11/01 +-<LI>Revised: 2004/04/10 +-<LI>Revised: 2004/04/28 +-<LI>Revised: 2004/08/30 +-<LI>Final: 2004/10/26 +-</UL> +-<!-- +- End special header. +- --> +- </div> +- +- <h1 class="nonheader">Table of Contents</h1> ++<h1>SRFI 43: Vector library</h1> ++ ++<p>by Taylor Campbell</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 43 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-43/srfi-43.html">https://srfi.schemers.org/srfi-43/srfi-43.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+43+at+srfi+dotschemers+dot+org">srfi-43@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-43">archive</a>.</p> ++<ul> ++<li>Received: 2003-03-26 ++</li><li>Draft: 2003-04-03--2003-06-01 ++</li><li>Revised: 2003-07-15 ++</li><li>Revised: 2003-11-01 ++</li><li>Revised: 2004-04-10 ++</li><li>Revised: 2004-04-28 ++</li><li>Revised: 2004-08-30 ++</li><li>Final: 2004-10-26 ++</li></ul> ++ ++ <h2 class="nonheader">Table of Contents</h2> + <ul class="outer"> + <li>1. <a href="#Abstract">Abstract</a></li> + <li>2. <a href="#Rationale">Rationale</a></li> +@@ -133,7 +122,7 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <li>8. <a href="#Copyright">Copyright</a></li> + </ul> + +- <h1 class="nonheader"><a name="Abstract">1. Abstract</a></h1> ++ <h2 class="nonheader"><a name="Abstract">1. Abstract</a></h2> + <p> + This <a href="#SRFI">SRFI</a> proposes a comprehensive and + complete library of vector operations accompanied by a freely +@@ -153,7 +142,7 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + structure / package / library / unit called <tt>vector-lib</tt>. + </p> + +- <h1 class="nonheader"><a name="Rationale">2. Rationale</a></h1> ++ <h2 class="nonheader"><a name="Rationale">2. Rationale</a></h2> + <p> + <a href="#R5RS">R5RS</a> provides very few list-processing + procedures, for which reason <a href="#SRFI-1">SRFI 1 +@@ -178,7 +167,7 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + + <p> + Many Scheme implementations provide several vector operations +- beyond the minuscule set that R5RS defines (the typical ++ beyond the miniscule set that R5RS defines (the typical + <tt><a href="#vector-append">vector-append</a></tt>, + <tt><a href="#vector-map">vector-map</a></tt>, et cetera), but + often these procedures have different names, take arguments in +@@ -194,9 +183,9 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + includes routines for sorting not only vectors but also lists. + </p> + +- <h1 class="nonheader"> ++ <h2 class="nonheader"> + <a name="ProcIndex">3. Procedure Index</a> +- </h1> ++ </h2> + <p> + Here is an index of the procedures provided by this package. + Those marked by <b>bold</b> are provided in +@@ -207,140 +196,140 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dl> + <dt class="proc-index"> + · <a href="#Constructors">Constructors</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <b><a href="#make-vector">make-vector</a></b> + <b><a href="#vector">vector</a></b> +- <br> +- <a href="#vector-tabulate">vector-unfold</a> ++ <br /> ++ <a href="#vector-unfold">vector-unfold</a> + <a href="#vector-unfold-right">vector-unfold-right</a> +- <br> ++ <br /> + <a href="#vector-copy">vector-copy</a> + <a href="#vector-reverse-copy">vector-reverse-copy</a> +- <br> ++ <br /> + <a href="#vector-append">vector-append</a> + <a href="#vector-concatenate">vector-concatenate</a> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Predicates">Predicates</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <b><a href="#vector-p">vector?</a></b> +- <br> ++ <br /> + <a href="#vector-empty-p">vector-empty?</a> +- <br> ++ <br /> + <a href="#vector-eq">vector=</a> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Selectors">Selectors</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <b><a href="#vector-ref">vector-ref</a></b> +- <br> ++ <br /> + <b><a href="#vector-length">vector-length</a></b> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Iteration">Iteration</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <a href="#vector-fold">vector-fold</a> + <a href="#vector-fold-right">vector-fold-right</a> +- <br> ++ <br /> + <a href="#vector-map">vector-map</a> + <a href="#vector-map-bang">vector-map!</a> +- <br> ++ <br /> + <a href="#vector-for-each">vector-for-each</a> +- <br> ++ <br /> + <a href="#vector-count">vector-count</a> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Searching">Searching</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <a href="#vector-index">vector-index</a> + <a href="#vector-index-right">vector-index-right</a> +- <br> ++ <br /> + <a href="#vector-skip">vector-skip</a> + <a href="#vector-skip-right">vector-skip-right</a> +- <br> ++ <br /> + <a href="#vector-binary-search">vector-binary-search</a> +- <br> ++ <br /> + <a href="#vector-any">vector-any</a> + <a href="#vector-every">vector-every</a> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Mutators">Mutators</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <b><a href="#vector-set-bang">vector-set!</a></b> + <a href="#vector-swap-bang">vector-swap!</a> +- <br> ++ <br /> + <b><i><a href="#vector-fill-bang">vector-fill!</a></i></b> +- <br> ++ <br /> + <a href="#vector-reverse-bang">vector-reverse!</a> +- <br> ++ <br /> + <a href="#vector-copy-bang">vector-copy!</a> + <a href="#vector-reverse-copy-bang">vector-reverse-copy!</a> +- <br> +- <br> ++ <br /> ++ <br /> + </code> + </dd> + + <dt class="proc-index"> + · <a href="#Conversion">Conversion</a> +- <br> +- <br> ++ <br /> ++ <br /> + </dt> + <dd> + <code> + <b><i><a href="#vector-to-list">vector->list</a></i></b> + <a href="#reverse-vector-to-list">reverse-vector->list</a> +- <br> ++ <br /> + <b><i><a href="#list-to-vector">list->vector</a></i></b> + <a href="#reverse-list-to-vector">reverse-list->vector</a> + </code> + </dd> + </dl> + +- <h1 class="nonheader"><a name="Procs">4. Procedures</a></h1> ++ <h2 class="nonheader"><a name="Procs">4. Procedures</a></h2> + <p> + In this section containing specifications of procedures, the + following notation is used to specify parameters and return +@@ -359,8 +348,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + implementation-dependant; this SRFI does not specify what it + returns, and in order to write portable code, the return value + should be ignored. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">vec</dt> +@@ -368,8 +357,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + The argument in this place must be a vector, i.e. it must + satisfy the predicate + <tt><a href="#vector-p">vector?</a></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">i, j, start, size</dt> +@@ -379,8 +368,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <tt>zero?</tt> or <tt>positive?</tt>. The third case of it + indicates the index at which traversal begins; the fourth case + of it indicates the size of a vector. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">end</dt> +@@ -389,18 +378,18 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + must satisfy the predicates <tt>integer?</tt> and + <tt>positive?</tt>. This indicates the index directly before + which traversal will stop — processing will occur until +- the index of the vector is <tt><i>end</i></tt>. It is the ++ the the index of the vector is <tt><i>end</i></tt>. It is the + closed right side of a range. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">f</dt> + <dd> + The argument in this place must be a function of one or more + arguments, returning exactly one value. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">pred?</dt> +@@ -408,8 +397,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + The argument in this place must be a function of one or more + arguments that returns one value, which is treated as a + boolean. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec"> +@@ -417,8 +406,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + </dt> + <dd> + The argument in this place may be any Scheme value. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">[something]</dt> +@@ -427,24 +416,24 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + argument; it needn't necessarily be applied. + <tt><i>Something</i></tt> needn't necessarily be one thing; for + example, this usage of it is perfectly valid: +- <br> +- <br> ++ <br /> ++ <br /> + <code> + [start [end]] + </code> +- <br> +- <br> ++ <br /> ++ <br /> + and is indeed used quite often. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec">something ···</dt> + <dd> + Indicates that zero or more <tt><i>something</i></tt>s are + allowed to be arguments. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec"> +@@ -454,8 +443,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dd> + Indicates that at least one <tt><i>something</i></tt> must be + arguments. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="type-spec"> +@@ -467,8 +456,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + Exactly equivalent to the previous argument notation, but this + also indicates that <tt><i>n</i></tt> will be used later in the + procedure description. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +@@ -478,9 +467,9 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + result when the end of the shortest vector is reached. The sole + exception is <tt><a href="#vector-eq">vector=</a></tt>, which + automatically returns <tt>#f</tt> if the vectors' lengths vary. +- <p> ++ </p> + +- <h2><a name="Constructors">4.1. Constructors</a></h2> ++ <h3 id="Constructors">4.1. Constructors</h3> + <dl> + <dt class="proc-spec"> + <a name="make-vector"> +@@ -493,20 +482,20 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + of size <tt><i>size</i></tt>, optionally filling it with + <tt><i>fill</i></tt>. The default value of + <tt><i>fill</i></tt> is unspecified. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (make-vector 5 3) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(3 3 3 3 3) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -518,20 +507,20 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dd> + [<a href="#R5RS"><i>R5RS</i></a>] Creates and returns a vector + whose elements are <tt><i>x ···</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector 0 1 2 3 4) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(0 1 2 3 4) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -552,46 +541,46 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + vector and <tt><i>n</i></tt> new seeds for the next iteration. + It is an error for the number of seeds to vary between + iterations. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-unfold (λ (i x) (values x (- x 1))) +- <br> ++ (vector-unfold (λ (i x) (values x (- x 1))) ++ <br /> + + 10 0) + </code> +- <br> ++ <br /> + <code class="example-value"> +- #(0 -1 -2 -3 -4 -5 -6 -7 -8 -9) ++ #(0 -1 -2 -3 -4 -5 -6 -7 -8 -8) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Construct a vector of the sequence of integers in the range + [0,<tt><i>n</i></tt>). +- <br> ++ <br /> + <code class="example-call"> + (vector-unfold values <tt><i>n</i></tt>) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(0 1 2 ··· <i>n-2</i> <i>n-1</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Copy <tt><i>vector</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-unfold (λ (i) (vector-ref <i>vector</i> i)) +- <br> ++ (vector-unfold (λ (i) (vector-ref <i>vector</i> i)) ++ <br /> + + (vector-length <i>vector</i>)) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -605,40 +594,40 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + Like <tt><a href="#vector-unfold">vector-unfold</a></tt>, but + it uses <tt><i>f</i></tt> to generate elements from + right-to-left, rather than left-to-right. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + Construct a vector in reverse of the integers in the range + [0,<tt><i>n</i></tt>). +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-unfold-right (λ (i x) (values x (+ x 1))) <i>n</i> 0) ++ (vector-unfold-right (λ (i x) (values x (+ x 1))) <i>n</i> 0) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(<i>n-1</i> <i>n-2</i> ··· 2 1 0) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Reverse <tt><i>vector</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-unfold-right (λ (i x) ++ (vector-unfold-right (λ (i x) + (values (vector-ref <i>vector</i> x) + (+ x 1))) +- <br> ++ <br /> + + (vector-length <i>vector</i>) +- <br> ++ <br /> + + 0) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <!-- VECTOR-TABULATE has been flushed in favour of VECTOR-UNFOLD. +@@ -652,29 +641,29 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + Creates a new vector whose size is <tt><i>size</i></tt> and + fills it by applying <tt><i>f</i></tt> to each index in the + vector, in an unspecified order. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-tabulate - 5) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(0 -1 -2 -3 -4) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-tabulate (λ (x) (* x x)) 5) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(0 1 4 9 16) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + --> + +@@ -698,47 +687,47 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + obviously cannot be filled by elements from <tt><i>vec</i></tt> + are filled with <tt><i>fill</i></tt>, whose default value is + unspecified. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-copy '#(a b c d e f g h i)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(a b c d e f g h i) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-copy '#(a b c d e f g h i) 6) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(g h i) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-copy '#(a b c d e f g h i) 3 6) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(d e f) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-copy '#(a b c d e f g h i) 6 12 'x) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(g h i x x x) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -752,20 +741,20 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + Like <tt><a href="#vector-copy">vector-copy</a></tt>, but it + copies the elements in the reverse order from + <tt><i>vec</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-reverse-copy '#(5 4 3 2 1 0) 1 5) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(1 2 3 4) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -778,38 +767,38 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + Returns a newly allocated vector that contains all elements in + order from the subsequent locations in <tt><i>vec + ···</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-append '#(x) '#(y)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(x y) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-append '#(a) '#(b c d)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(a b c d) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-append '#(a #(b)) '#(#(c))) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(a #(b) #(c)) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -821,33 +810,33 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dd> + Appends each vector in <tt><i>list-of-vectors</i></tt>. This + is equivalent to: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="indented"> + (apply <a href="#vector-append">vector-append</a> + <i>list-of-vectors</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + However, it may be implemented better. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-concatenate '(#(a b) #(c d))) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(a b c d) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Predicates">4.2. Predicates</a></h2> ++ <h3 id="Predicates">4.2. Predicates</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-p"> +@@ -859,56 +848,56 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + [<a href="#R5RS"><i>R5RS</i></a>] Disjoint type predicate for + vectors: this returns <tt>#t</tt> if <tt><i>x</i></tt> is a + vector, and <tt>#f</tt> if otherwise. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector? '#(a b c)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector? '(a b c)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector? #t) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector? '#()) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector? '()) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -920,47 +909,47 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dd> + Returns <tt>#t</tt> if <tt><i>vec</i></tt> is empty, i.e. its + length is <tt>0</tt>, and <tt>#f</tt> if not. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-empty? '#(a)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-empty? '#(())) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-empty? '#(#())) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-empty? '#()) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -986,101 +975,101 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + (The reference implementation does, but it does not consider + the situation where <tt><i>elt=?</i></tt> is in fact itself + <tt>eq?</tt> to avoid yet more unnecessary comparisons.) +- <br> +- <br> ++ <br /> ++ <br /> + If there are only zero or one vector arguments, <tt>#t</tt> is + automatically returned. The dynamic order in which comparisons + of elements and of vectors are performed is left completely + unspecified; do not rely on a particular order. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= eq? '#(a b c d) '#(a b c d)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= eq? '#(a b c d) '#(a b d c)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= = '#(1 2 3 4 5) '#(1 2 3 4)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= = '#(1 2 3 4) '#(1 2 3 4)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + The two trivial cases. +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= eq?) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= eq? '#(a)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Note the fact that we don't use vector literals in the next two + — it is unspecified whether or not literal vectors with + the same external representation are <tt>eq?</tt>. +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= eq? (vector (vector 'a)) (vector (vector 'a))) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector= equal? (vector (vector 'a)) (vector (vector 'a))) + </code> +- <br> ++ <br /> + <code class="example-value"> + #t + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Selectors">4.3. Selectors</a></h2> ++ <h3 id="Selectors">4.3. Selectors</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-ref"> +@@ -1095,20 +1084,20 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + on zero. <tt><i>I</i></tt> must be within the range [0, + <tt>(<a href="#vector-length">vector-length</a> + <i>vec</i>)</tt>). +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-ref '#(a b c d) 2) + </code> +- <br> ++ <br /> + <code class="example-value"> + c + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1124,24 +1113,24 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <tt><i>vec</i></tt> refers to a larger vector that contains + more locations that are unreachable from <tt><i>vec</i></tt>. + This SRFI does not define vector slices, but later SRFIs may.) +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-length '#(a b c)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 3 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Iteration">4.4. Iteration</a></h2> ++ <h3 id="Iteration">4.4. Iteration</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-fold"> +@@ -1167,50 +1156,50 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + becomes whatever <tt><i>kons</i></tt> returned at the + respective iteration —, and <tt><i>i</i></tt> is the + current index. +- <br> +- <br> ++ <br /> ++ <br /> + The iteration is strictly left-to-right. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + Find the longest string's length in + <tt><i>vector-of-strings</i></tt>. +- <br> ++ <br /> + <code class="example-call"> +- (vector-fold (λ (index len str) ++ (vector-fold (λ (index len str) + (max (string-length str) len)) +- <br> ++ <br /> + + 0 <i>vector-of-strings</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Produce a list of the reversed elements of + <tt><i>vec</i></tt>. +- <br> ++ <br /> + <code class="example-call"> +- (vector-fold (λ (index tail elt) (cons elt tail)) +- <br> ++ (vector-fold (λ (index tail elt) (cons elt tail)) ++ <br /> + + '() <i>vec</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Count the number of even numbers in <tt><i>vec</i></tt>. +- <br> ++ <br /> + <code class="example-call"> +- (vector-fold (λ (index counter n) +- <br> ++ (vector-fold (λ (index counter n) ++ <br /> + + (if (even? n) (+ counter 1) counter)) +- <br> ++ <br /> + + 0 <i>vec</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1224,26 +1213,26 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <dd> + Similar to <tt><a href="#vector-fold">vector-fold</a></tt>, but + it iterates right to left instead of left to right. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + Convert a vector to a list. +- <br> ++ <br /> + <code class="example-call"> +- (vector-fold-right (λ (index tail elt) ++ (vector-fold-right (λ (index tail elt) + (cons elt tail)) +- <br> ++ <br /> + + '() '#(a b c d)) + </code> +- <br> ++ <br /> + <code class="example-value"> + (a b c d) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1267,83 +1256,83 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + ···)</tt>. + The dynamic order of application of <tt><i>f</i></tt> is + unspecified. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-map (λ (i x) (* x x)) +- <br> ++ (vector-map (λ (i x) (* x x)) ++ <br /> + + (<a href="#vector-unfold">vector-unfold</a> +- (λ (i x) (values x (+ x 1))) ++ (λ (i x) (values x (+ x 1))) + 4 1)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(1 4 9 16) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-map (λ (i x y) (* x y))<br> ++ (vector-map (λ (i x y) (* x y))<br /> + + (<a href="#vector-unfold">vector-unfold</a> +- (λ (i x) (values x (+ x 1))) +- 5 1)<br> ++ (λ (i x) (values x (+ x 1))) ++ 5 1)<br /> + + (<a href="#vector-unfold">vector-unfold</a> +- (λ (i x) (values x (- x 1))) ++ (λ (i x) (values x (- x 1))) + 5 5)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(5 8 9 8 5) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (let ((count 0)) + </code> +- <br> ++ <br /> + <code class="example-call"> + +- (vector-map (λ (ignored-index ignored-elt) ++ (vector-map (λ (ignored-index ignored-elt) + </code> +- <br> ++ <br /> + <code class="example-call"> + + + (set! count (+ count 1)) + </code> +- <br> ++ <br /> + <code class="example-call"> + + + count) + </code> +- <br> ++ <br /> + <code class="example-call"> + + + '#(a b))) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(1 2) <i>OR</i> #(2 1) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-map (λ (i elt) (+ i elt)) '#(1 2 3 4)) ++ (vector-map (λ (i elt) (+ i elt)) '#(1 2 3 4)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #(1 3 5 7) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1363,8 +1352,8 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <tt><a href="#vector-ref">vector-ref</a></tt> or + <tt><a href="#vector-set-bang">vector-set!</a></tt> to + <tt><i>vec<sub>1</sub></i></tt> in <tt><i>f</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1384,31 +1373,31 @@ You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-43/mail + <tt><a href="#vector-map">vector-map</a></tt>, <tt><i>f</i></tt> + is reliably applied to each subsequent elements, starting at + index 0, in the vectors. +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-for-each (λ (i x) (display x) (newline)) ++ (vector-for-each (λ (i x) (display x) (newline)) + </code> +- <br> ++ <br /> + <code class="example-call"> + + + '#("foo" "bar" "baz" "quux" "zot")) + </code> +- <br> ++ <br /> + Displays: +- <br> ++ <br /> + <pre> + foo + bar + baz + quux + zot</pre> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1425,35 +1414,35 @@ zot</pre> + — where <tt><i>length</i></tt> is the length of the + smallest vector argument —, to <tt><i>i</i></tt> and each + parallel element in the vectors at that index, in order. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-count (λ (i elt) (even? elt)) ++ (vector-count (λ (i elt) (even? elt)) + '#(3 1 4 1 5 9 2 5 6)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 3 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> +- (vector-count (λ (i x y) (< x y)) ++ (vector-count (λ (i x y) (< x y)) + '#(1 3 6 9) '#(2 4 6 8 10 12)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 2 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Searching">4.5. Searching</a></h2> ++ <h3 id="Searching">4.5. Searching</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-index"> +@@ -1468,38 +1457,38 @@ zot</pre> + ···</i></tt> that satisfy + <tt><i>pred?</i></tt>. If no matching element is found by the + end of the shortest vector, <tt>#f</tt> is returned. +- <br> +- <br> ++ <br /> ++ <br /> + Examples: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-index even? '#(3 1 4 1 5 9)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 2 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-index < '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 1 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-index = '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2)) + </code> +- <br> ++ <br /> + <code class="example-value"> + #f + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1513,8 +1502,8 @@ zot</pre> + Like <tt><a href="#vector-index">vector-index</a></tt>, but it + searches right-to-left, rather than left-to-right, and all of + the vectors <i>must</i> have the same length. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1531,34 +1520,34 @@ zot</pre> + <tt><i>pred?</i></tt>. If all the values in the vectors + satisfy <tt><i>pred?</i></tt> until the end of the shortest + vector, this returns <tt>#f</tt>. This is equivalent to: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="indented"> + (<a href="#vector-index">vector-index</a> +- (λ (x<sub><i>1</i></sub> x<sub><i>2</i></sub> ++ (λ (x<sub><i>1</i></sub> x<sub><i>2</i></sub> + <i>···</i>) + (not (<i>pred?</i> x<sub><i>1</i></sub> + x<sub><i>1</i></sub> + <i>···</i>))) +- <br> ++ <br /> + + <i>vec<sub>1</sub> vec<sub>2</sub> + ···</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + Example: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="example-call"> + (vector-skip number? '#(1 2 a b 3 4 c d)) + </code> +- <br> ++ <br /> + <code class="example-value"> + 2 + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1573,23 +1562,23 @@ zot</pre> + searches for a non-matching element right-to-left, rather than + left-to-right, and all of the vectors <i>must</i> have the same + length. This is equivalent to: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="indented"> + (<a href="#vector-index">vector-index-right</a> +- (λ (x<sub><i>1</i></sub> x<sub><i>2</i></sub> ++ (λ (x<sub><i>1</i></sub> x<sub><i>2</i></sub> + <i>···</i>) + (not (<i>pred?</i> x<sub><i>1</i></sub> + x<sub><i>1</i></sub> + <i>···</i>))) +- <br> ++ <br /> + + + <i>vec<sub>1</sub> vec<sub>2</sub> + ···</i>) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1610,31 +1599,31 @@ zot</pre> + integer, which indicates that the first argument is greater + than the second argument. An example <tt><i>cmp</i></tt> might + be: +- <br> +- <br> ++ <br /> ++ <br /> + <code class="indented"> +- (λ (<i>char<sub>1</sub></i> <i>char<sub>2</sub></i>) ++ (λ (<i>char<sub>1</sub></i> <i>char<sub>2</sub></i>) + </code> +- <br> ++ <br /> + <code class="indented"> + (cond ((char<? <i>char<sub>1</sub> + char<sub>2</sub></i>) + -1) + </code> +- <br> ++ <br /> + <code class="indented"> + + ((char=? <i>char<sub>1</sub> + char<sub>2</sub></i>) + 0) + </code> +- <br> ++ <br /> + <code class="indented"> + + (else 1))) + </code> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1652,8 +1641,8 @@ zot</pre> + set of elements exists, <tt>vector-any</tt> returns the value + that <tt><i>pred?</i></tt> returned for that set of elements. + The iteration is strictly left-to-right. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1675,12 +1664,12 @@ zot</pre> + the value that <tt><i>pred?</i></tt> returned for the last + set of elements, at the last index of the shortest vector. The + iteration is strictly left-to-right. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Mutators">4.6. Mutators</a></h2> ++ <h3 id="Mutators">4.6. Mutators</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-set-bang"> +@@ -1691,8 +1680,8 @@ zot</pre> + <dd> + [<a href="#R5RS"><i>R5RS</i></a>] Assigns the contents of the location at <tt><i>i</i></tt> in + <tt><i>vec</i></tt> to <tt><i>value</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1705,8 +1694,8 @@ zot</pre> + Swaps or exchanges the values of the locations in + <tt><i>vec</i></tt> at <tt><i>i</i></tt> & + <tt><i>j</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1720,8 +1709,8 @@ zot</pre> + between <tt><i>start</i></tt>, which defaults to <tt>0</tt> and + <tt><i>end</i></tt>, which defaults to the length of + <tt><i>vec</i></tt>, to <tt><i>fill</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1736,8 +1725,8 @@ zot</pre> + and <tt><i>end</i></tt>. <tt><i>Start</i></tt> defaults to + <tt>0</tt> and <tt><i>end</i></tt> defaults to the length of + <tt><i>vec</i></tt>. Note that this does not deeply reverse. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1758,8 +1747,8 @@ zot</pre> + <i>sstart</i>)</tt>. <tt><i>Sstart</i></tt> defaults to + <tt>0</tt> and <tt><i>send</i></tt> defaults to the length of + <tt><i>source</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1783,12 +1772,12 @@ zot</pre> + <i>send</i>) + </tt> + would. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h2><a name="Conversion">4.7. Conversion</a></h2> ++ <h3 id="Conversion">4.7. Conversion</h3> + <dl> + <dt class="proc-spec"> + <a name="vector-to-list"> +@@ -1801,8 +1790,8 @@ zot</pre> + between <tt><i>start</i></tt>, which defaults to <tt>0</tt>, + and <tt><i>end</i></tt>, which defaults to the length of + <tt><i>vec</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1815,9 +1804,9 @@ zot</pre> + <dd> + Like <tt><a href="#vector-to-list">vector->list</a></tt>, + but the resulting list contains the elements in reverse between +- the specified range. +- <br> +- <br> ++ the the specified range. ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1827,8 +1816,8 @@ zot</pre> + </dt> + <dd> + [<a href="#R5RS"><i>R5RS</i></a>+] Creates a vector of elements from <tt><i>proper-list</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="proc-spec"> +@@ -1840,31 +1829,31 @@ zot</pre> + Like <tt><a href="#list-to-vector">list->vector</a></tt>, + but the resulting list contains the elements in reverse of + <tt><i>proper-list</i></tt>. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + </dl> + +- <h1 class="nonheader"> ++ <h2 class="nonheader"> + <a name="RefImpl">5. Reference Implementation</a> +- </h1> ++ </h2> + <p> + With this SRFI comes a complete reference implementation. It is + licensed under a very open copyright with which no implementors + should have any legal issues. +- <br> +- <br> ++ <br /> ++ <br /> + The reference implementation has only one non-R5RS dependency: + <a href="#SRFI-23">SRFI 23</a>'s <tt>error</tt> procedure. +- <br> +- <br> ++ <br /> ++ <br /> + This reference implementation of all the procedures described in +- this SRFI can be found <a href="#vector-lib.scm">here</a>. ++ this SRFI can be found <a href="https://srfi.schemers.org/srfi-43/vector-lib.scm">here</a>. + </p> + +- <h1 class="nonheader"> ++ <h2 class="nonheader"> + <a name="Acknowledgements">6. Acknowledgements</a> +- </h1> ++ </h2> + <p> + Thanks to Olin Shivers for his wonderfully complete + <a href="#SRFI-1">list</a> and <a href="#SRFI-13">string</a> +@@ -1882,102 +1871,102 @@ zot</pre> + attention to the SRFI. + </p> + +- <h1 class="nonheader"><a name="References">7. References</a></h1> ++ <h2 class="nonheader"><a name="References">7. References</a></h2> + <dl> + <dt class="ref"><a name="R5RS">R5RS</a></dt> + <dd> + <i>R5RS: The Revised<sup>5</sup> Report on Scheme</i> +- <br> ++ <br /> + R. Kelsey, W. Clinger, J. Rees (editors). +- <br> ++ <br /> + Higher-Order and Symbolic Computation, Vol. 11, No. 1, + September, 1998 +- <br> ++ <br /> + and +- <br> ++ <br /> + ACM SIGPLAN Notices, Vol. 33, No. 9, October, 1998 +- <br> ++ <br /> + Available at: + <a href="http://www.schemers.org/Documents/Standards/R5RS/"> + http://www.schemers.org/Documents/Standards/R5RS/ + </a> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="ref"><a name="SRFI">SRFI</a></dt> + <dd> + <i>SRFI: Scheme Request for Implementation</i> +- <br> ++ <br /> + The SRFI website can be found at: +- <a href="http://srfi.schemers.org/"> +- http://srfi.schemers.org/ ++ <a href="https://srfi.schemers.org/"> ++ https://srfi.schemers.org/ + </a> +- <br> ++ <br /> + The SRFIs mentioned in this document are described later. +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="ref"><a name="SRFI-1">SRFI 1</a></dt> + <dd> + <i>SRFI 1: List Library</i> +- <br> ++ <br /> + A SRFI of list processing procedures, written by Olin Shivers. +- <br> ++ <br /> + Available at: +- <a href="http://srfi.schemers.org/srfi-1/"> +- http://srfi.schemers.org/srfi-1/ ++ <a href="srfi-1.html"> ++ https://srfi.schemers.org/srfi-1/ + </a> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="ref"><a name="SRFI-13">SRFI 13</a></dt> + <dd> + <i>SRFI 13: String Library</i> +- <br> ++ <br /> + A SRFI of string processing procedures, written by Olin + Shivers. +- <br> ++ <br /> + Available at: +- <a href="http://srfi.schemers.org/srfi-13/"> +- http://srfi.schemers.org/srfi-13/ ++ <a href="srfi-13.html"> ++ https://srfi.schemers.org/srfi-13/ + </a> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="ref"><a name="SRFI-23">SRFI 23</a></dt> + <dd> + <i>SRFI 23: Error Reporting Mechanism</i> +- <br> ++ <br /> + A SRFI that defines a new primitive (<tt>error</tt>) for + reporting that an error occurred, written by Stephan Houben. +- <br> ++ <br /> + Available at: +- <a href="http://srfi.schemers.org/srfi-23/"> +- http://srfi.schemers.org/srfi-23/ ++ <a href="srfi-23.html"> ++ https://srfi.schemers.org/srfi-23/ + </a> +- <br> +- <br> ++ <br /> ++ <br /> + </dd> + + <dt class="ref"><a name="SRFI-32">SRFI 32</a></dt> + <dd> + <i>SRFI 32: Sort Libraries (draft)</i> +- <br> ++ <br /> + A SRFI of list and vector sorting routines, written by Olin + Shivers. +- <br> ++ <br /> + Available at: +- <a href="http://srfi.schemers.org/srfi-32/"> +- http://srfi.schemers.org/srfi-32/ ++ <a href="https://srfi.schemers.org/srfi-32/"> ++ https://srfi.schemers.org/srfi-32/ + </a> + </dd> + </dl> + +- <h1 class="nonheader"><a name="Copyright">8. Copyright</a></h1> ++ <h2 class="nonheader"><a name="Copyright">8. Copyright</a></h2> + <p> + Copyright (C) Taylor Campbell (2003). All rights reserved. + </p> +@@ -2005,7 +1994,7 @@ zot</pre> + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + </p> +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-45.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-45.html +index a9c326b..b828b96 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-45.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-45.html +@@ -1,40 +1,53 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-45 ┃ ++┃ Commit: 6115a28f2c1d24b3922779e0f14cb55754cb76cf ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 45: Primitives for expressing iterative lazy algorithms</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +- <H1>Title</H1> ++ <h1>SRFI 45: Primitives for Expressing Iterative Lazy Algorithms</h1> + +- SRFI 45: Primitives for Expressing Iterative Lazy Algorithms +- +- <H1>Author</H1> +- +- André van Tonder ++ <p>by André van Tonder</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 45 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-45/srfi-45.html">https://srfi.schemers.org/srfi-45/srfi-45.html</a>.</p></blockquote></blockquote></blockquote> + +- <H1>Status</H1> +- +- This SRFI is currently in ``final'' status. To see an explanation +- of each status that a SRFI can hold, see <A +- HREF="http://srfi.schemers.org/srfi-process.html">here</A>. You +- can access previous messages via <a +- href="http://srfi.schemers.org/srfi-45/mail-archive/maillist.html"> +- the archive of the mailing list</a>. ++ <h2>Status</h2> + +- <p> +- <ul> +- <li>Received: 2003/09/20</li> +- <li>Draft: 2003/09/23-2003/12/23</li> +- <li>Revised: 2003/12/20</li> +- <li>Revised: 2004/03/06</li> +- <li>Final: 2004/04/05</li> +- <li>Bug fix: 2004/08/04</li> ++ <p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+45%20%20+at+srfi+dotschemers+dot+org">srfi-45 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-45">archive</a>.</p> ++<ul> ++ <li>Received: 2003-09-20</li> ++ <li>Draft: 2003-09-23--2003-12-23</li> ++ <li>Revised: 2003-12-20</li> ++ <li>Revised: 2004-03-06</li> ++ <li>Final: 2004-04-05</li> ++ <li>Bug fix: 2004-08-04</li> + </ul> + +- <H1>Abstract</H1> +- ++ <h2>Abstract</h2> ++<p> + Lazy evaluation is traditionally simulated in Scheme using + <code>delay</code> and <code>force</code>. However, these + primitives are not powerful enough to express +@@ -44,38 +57,38 @@ typical iterative lazy algorithms written using + <code>delay</code> and + <code>force</code> will often + require unbounded memory. +- ++</p> + <p> + Although varous modifications of <code>delay</code> and + <code>force</code> had been proposed to resolve this problem (see e.g., the +-<a href= +-http://srfi.schemers.org/srfi-40/mail-archive/maillist.html> ++<a href="https://srfi-email.schemers.org/srfi-40/"> + SRFI-40 discussion list + </a>) + they all fail some of the benchmarks provided below. To our knowledge, + the current SRFI provides the first exhaustive solution to this problem. +- +- ++</p> + <p> + As motivation, + we first explain how the usual laziness encoding using only <code>delay</code> + and <code>force</code> will break the iterative behavior of typical + algorithms that would have been properly tail-recursive +-in a true lazy language, causing the computation to require unbounded memory. +- ++in a true lazy language, causing the computation to require unbounded memory. ++</p> + <p> + The problem is then resolved by + introducing a set of three operations: ++</p> + <pre> + {<code>lazy</code>, <code>delay</code>, <code>force</code>} + </pre> ++<p> + which allow the programmer to succinctly express lazy algorithms while + retaining bounded space behavior in cases that are properly tail-recursive. + A general + recipe for using these primitives is provided. An additional procedure + <code>{eager}</code> is provided for the construction of + eager promises in cases where efficiency is a concern. +- ++</p> + <p> + Although this SRFI redefines <code>delay</code> and <code>force</code>, + the extension is conservative in the sense that the semantics of the subset {<code>delay</code>, <code>force</code>} in +@@ -83,27 +96,28 @@ isolation (i.e., as long as the program does not use <code>lazy</code>) + agrees with that in R5RS. In other words, no program that uses the + R5RS definitions of delay and force will break if those definition are + replaced by the SRFI-45 definitions of delay and force. ++</p> + + + +- +- <H1>Rationale</H1> +- ++ <h2>Rationale</h2> ++<p> + Wadler et al. in the paper + <em>How to add laziness to a strict language without even being odd</em> [Wad98], provide a + straightforward recipe for transforming arbitrary lazy data structures and algorithms + into a strict language using <code>delay</code> and <code>force</code>. +- ++</p> + <p> +-However, it is known (see e.g. the <a href="http://srfi.schemers.org/srfi-40/mail-archive/maillist.html">SRFI-40 discussion list</a>) that this ++However, it is known (see e.g. the <a href="https://srfi-email.schemers.org/srfi-40/">SRFI-40 discussion list</a>) that this + transformation can lead to programs that suffer from unbounded space + consumption, even if the original lazy algorithm was properly tail-recursive. ++</p> + +-<H2>Example</H2> +- ++<h3>Example</h3> ++<p> + Consider the following procedure, written in a hypothetical lazy + language with Scheme syntax: +- ++</p> + <pre> + (define (stream-filter p? s) + (if (null? s) '() +@@ -113,10 +127,10 @@ language with Scheme syntax: + (cons h (stream-filter p? t)) + (stream-filter p? t))))) + </pre> +- ++<p> + According to the tranformation proposed in [Wad98], this algorithm can be espressed as follows + in Scheme: +- ++</p> + <pre> + (define (stream-filter p? s) + (delay (force +@@ -127,8 +141,9 @@ in Scheme: + (delay (cons h (stream-filter p? t))) + (stream-filter p? t))))))) + </pre> +- ++<p> + The recipe, <em>which we will modify below</em>, is as follows: ++</p> + <ul> + <li> + wrap all constructors (e.g., <code>'()</code>, <code>cons</code>) with <code>delay</code>, +@@ -149,6 +164,7 @@ will cause a typical Scheme + implementation to run out of memory, despite the fact that + the original (lazy) algorithm was iterative, only needing tail calls to evaluate the + first element of the result stream. ++</p> + <pre> + (define (from n) + (delay (cons n (from (+ n 1))))) +@@ -160,32 +176,34 @@ first element of the result stream. + </pre> + + +-<h2>Why the space leak occurs</h2> +- ++<h3>Why the space leak occurs</h3> ++<p> + The problem occurring in the above + <code>stream-filter</code> example can already + be seen in the following simple infinite loop, expressed in our hypothetical lazy + language as: +- ++</p> + <pre> + (define (loop) (loop)) + </pre> +- ++<p> + which becomes, according to the [Wad98] transformation ++</p> + <pre> + (define (loop) (delay (force (loop)))) + </pre> +- ++<p> + Taking the semantics of {<code>delay</code>, <code>force</code>} + to be informally: +- ++</p> + <pre> + (force (delay expr)) = update promise : (delay expr) + with value of expr + return value in promise + </pre> +- ++<p> + we get ++</p> + <pre> + (force (loop)) = update promise1 : (delay (force (loop))) + with value of (force (loop)) +@@ -207,13 +225,13 @@ we get + return value in promise1 + = ... + </pre> +- ++<p> + We see that an ever growing sequence of pending promises builds up until the heap + is exhausted. ++</p> + +- +-<h2>Why the above is not call-by-need</h2> +- ++<h3>Why the above is not call-by-need</h3> ++<p> + Expressing the above algorithm in terms of {<code>delay</code>, <code>force</code>} + in fact does not correctly capture common notions of + call-by-need evaluation semantics. For example, +@@ -221,7 +239,7 @@ in a call-by-need language with naive graph reduction semantics, the above algor + would run in bounded space since naive graph reduction is known to be + tail-safe. For a good discussion of this issue, see e.g. R. Jones - + <em>Tail recursion without space leaks</em> [Jon98]. +- ++</p> + <p> + Our problem may be regarded as analogous to graph reduction, + with promises corresponding to graph nodes and +@@ -230,31 +248,30 @@ one has to be careful with + the order in which nodes are evaluated and overwritten to avoid space + leaks. In our context this would correspond to the order in which + promises are evaluated and overwritten when forced. +- ++</p> + <p> + In the above example, naive graph reduction would correspond to the + promise at the root being overwritten at each step <em>before</em> + the next iteration is evaluated, thus avoiding the need for a growing + sequence of unfulfilled promises representing (unnecessary) future + copy operations. ++</p> + +- +-<h2>The solution</h2> +- ++<h3>The solution</h3> ++<p> + The accumulation of unnecessary promises in the above examples is a consequence + of suspensions being forced in increasingly nested contexts. In order + to correctly simulate naive graph reduction + we should instead find a way of forcing tail suspensions <em>iteratively</em>, + each time overwriting the previous result. +- +- ++</p> + <p> + A solution to this problem exists and is described (in a different context) in + <em>Compiling higher order languages into fully tail-recursive portable C</em> + - Feely et al. [Fee97]. This reference introduces a method + widely known as the <em>trampoline technique</em> for evaluating + tail contexts iteratively. +- ++</p> + <p> + Adapting the trampoline technique to the situation at hand, we + introduce a new primitive <code>lazy</code>, which behaves like +@@ -262,7 +279,7 @@ an "atomic" <code>(delay (force ...))</code>, and which will + replace the combination <code>(delay (force ...))</code> at procedure + entry points. We also + redefine <code>delay</code> and <code>force</code> as below: +- ++</p> + <pre> + ; type Promise a = lazy (Promise a) | eager a + +@@ -298,19 +315,18 @@ redefine <code>delay</code> and <code>force</code> as below: + (define unbox car) + (define set-box! set-car!) + </pre> +- +- +- ++<p> + Our example is then coded (see the full recipe below) ++</p> + <pre> + (define (loop) (lazy (loop))) + </pre> +- ++<p> + When we now evaluate <code>(force (loop))</code>, + the <code>force</code> procedure will execute a top-level loop + which will iteratively evaluate and overwrite subsequent +-suspensions. +- ++suspensions. ++</p> + <p> + In the language of [Fee97], + the iterative loop in <code>force</code> plays the role of +@@ -321,63 +337,81 @@ This technique is tail-safe because lazy procedures, instead of calling + other lazy procedures directly, simply return a + suspension representing a control point to be called upon the next iteration + of the dispatcher loop in <code>force</code>. For more details, see [FMRW]. ++</p> + +- +- <H1>Specification</H1> +- ++ <h2>Specification</h2> ++<p> + The following macros should be provided. The semantics, which is informally + described here, should conform to that of the reference implementation below: ++</p> + <ul> +-<li> +-<code><a name="delay">(delay expression)</a></code>: ++ <li> ++ <p> ++<code id="delay">(delay expression)</code>: + Takes an expression of arbitrary type a and returns a promise of type (Promise a) + which at some point in the future may be asked (by the force procedure) + to evaluate the expression and deliver the resulting value. +-<li> +-<code><a name="lazy">(lazy expression)</a></code>: ++ </p> ++ </li> ++ <li> ++ <p> ++<code id="lazy">(lazy expression)</code>: + Takes an expression of type (Promise a) and returns a promise of type (Promise a) + which at some point in the future may be asked (by the force procedure) + to evaluate the expression and deliver the resulting promise. ++ </p> ++ </li> + </ul> + ++<p> + The following procedures should be provided: ++</p> + <ul> +-<li> +-<code><a name="force">(force expression)</a></code>: ++ <li> ++ <p> ++<code id="force">(force expression)</code>: + Takes an argument of type (Promise a) and returns a value of type a as follows: + If a value of type a has been computed for the promise, this value is returned. + Otherwise, the promise is first evaluated, then overwritten by the obtained promise + or value, + and then <code>force</code> is again applied (iteratively) to the promise. +-<li> +-<code><a name="eager">(eager expression)</a></code>: ++ </p> ++ </li> ++ <li> ++ <p> ++<code id="eager">(eager expression)</code>: + Takes an argument of type a and returns a value of type Promise a. As opposed + to <code>delay</code>, the argument is evaluated eagerly. Semantically, + writing <code>(eager expression)</code> is equivalent to writing ++ </p> + <pre> + (let ((value expression)) (delay value)). + </pre> ++ <p> + However, the former is more efficient since it does not require unnecessary + creation and evaluation of thunks. We also have the equivalence ++ </p> + <pre> + (delay expression) = (lazy (eager expression)) + </pre> ++ </li> + </ul> + +- ++<p> + The following reduction rules may be helpful for reasoning about + these primitives. However, they do not express the memoization and + memory usage + semantics specified above: ++</p> + <pre> +- (force (delay expression)) -> expression +- (force (lazy expression)) -> (force expression) +- (force (eager value)) -> value ++ (force (delay expression)) -> expression ++ (force (lazy expression)) -> (force expression) ++ (force (eager value)) -> value + </pre> + + <p> + The typing can be succinctly expressed as follows: +- ++</p> + <pre> + + type Promise a = lazy (Promise a) | eager a +@@ -405,19 +439,23 @@ Although this SRFI specifies an extension to the semantics of <code>force</code> + the extension is conservative in the sense that the semantics of the subset {<code>delay</code>, <code>force</code>} in + isolation (i.e., as long as the program does not use <code>lazy</code>) + agrees with that in R5RS. +- +- <H1>Correct usage</H1> +- ++</p> ++ <h2>Correct usage</h2> ++<p> + We now provide a general + recipe for using the primitives ++</p> + <pre> + {<code>lazy</code>, <code>delay</code>, <code>force</code>} + </pre> ++<p> + to express lazy algorithms in Scheme. +- ++</p> ++<p> + The transformation is best described by way of an example: Consider + again the stream-filter algorithm, expressed in a hypothetical lazy language + as ++</p> + <pre> + (define (stream-filter p? s) + (if (null? s) '() +@@ -427,10 +465,10 @@ as + (cons h (stream-filter p? t)) + (stream-filter p? t))))) + </pre> +- ++<p> + This algorithm can be espressed as follows + in Scheme: +- ++</p> + <pre> + (define (stream-filter p? s) + (lazy +@@ -441,8 +479,9 @@ in Scheme: + (delay (cons h (stream-filter p? t))) + (stream-filter p? t)))))) + </pre> +- ++<p> + In other words, we ++</p> + <ul> + <li> + wrap all constructors (e.g., <code>'(), cons</code>) with <code>delay</code>, +@@ -455,22 +494,22 @@ In other words, we + wrap procedure bodies with <code>(lazy ...)</code>. + </li> + </ul> +- ++<p> + The only difference with the [Wad98] transformation described above is + in replacing the combination <code>(delay (force ...))</code> with + <code>(lazy ...)</code> in the third rule. +- ++</p> + <p> + More examples are included in the reference implementation below. +- +- ++</p> + +- <H1>Implementation</H1> + ++ <h2>Implementation</h2> ++<p> + The reference implementation uses the macro + mechanism of R5RS. + It does not use any other SRFI or any library. +- ++</p> + <p> + A collection of benchmarks is provided. + These check some special cases of the mechanism defined +@@ -480,11 +519,9 @@ a metric, left unspecified here, for deciding whether the memory + usage is bounded. A leak benchmark is passed if the memory usage + is bounded. + Passing the tests does not mean a correct implementation. ++</p> + +- +-<h2> +-Reference implementation +-</h2> ++<h3>Reference implementation</h3> + + <pre> + ;========================================================================= +@@ -536,7 +573,7 @@ Reference implementation + + (force s) + (force s) +- ;===> Should display 'hello once ++ ;===> Should display 'hello once + + ;========================================================================= + ; Memoization test 2: +@@ -544,7 +581,7 @@ Reference implementation + (let ((s (delay (begin (display 'bonjour) 2)))) + (+ (force s) (force s))) + +- ;===> Should display 'bonjour once ++ ;===> Should display 'bonjour once + + ;========================================================================= + ; Memoization test 3: (pointed out by Alejandro Forero Cuervo) +@@ -555,7 +592,7 @@ Reference implementation + + (force t) + (force r) +- ;===> Should display 'hi once ++ ;===> Should display 'hi once + + ;========================================================================= + ; Memoization test 4: Stream memoization +@@ -576,7 +613,7 @@ Reference implementation + (car (force (stream-drop s 4))) + (car (force (stream-drop s 4))) + +- ;===> Should display 'ho five times ++ ;===> Should display 'ho five times + + ;========================================================================= + ; Reentrancy test 1: from R5RS +@@ -584,13 +621,13 @@ Reference implementation + (define count 0) + (define p + (delay (begin (set! count (+ count 1)) +- (if (> count x) ++ (if (> count x) + count + (force p))))) + (define x 5) +-(force p) ;===> 6 ++(force p) ;===> 6 + (set! x 10) +-(force p) ;===> 6 ++(force p) ;===> 6 + + + ;========================================================================= +@@ -605,7 +642,7 @@ Reference implementation + (force f)) + 'second)))) + +-(force f) ;===> 'second ++(force f) ;===> 'second + + ;========================================================================= + ; Reentrancy test 3: due to John Shutt +@@ -613,7 +650,7 @@ Reference implementation + (define q + (let ((count 5)) + (define (get-count) count) +- (define p (delay (if (<= count 0) ++ (define p (delay (if (<= count 0) + count + (begin (set! count (- count 1)) + (force p) +@@ -623,9 +660,9 @@ Reference implementation + (define get-count (car q)) + (define p (cadr q)) + +-(get-count) ; => 5 +-(force p) ; => 0 +-(get-count) ; => 10 ++(get-count) ; => 5 ++(force p) ; => 0 ++(get-count) ; => 10 + + ;========================================================================= + ; Test leaks: All the leak tests should run in bounded space. +@@ -634,14 +671,14 @@ Reference implementation + ; Leak test 1: Infinite loop in bounded space. + + (define (loop) (lazy (loop))) +-;(force (loop)) ;==> bounded space ++;(force (loop)) ;==> bounded space + + ;========================================================================= + ; Leak test 2: Pending memos should not accumulate + ; in shared structures. + + (define s (loop)) +-;(force s) ;==> bounded space ++;(force s) ;==> bounded space + + ;========================================================================= + ; Leak test 3: Safely traversing infinite stream. +@@ -652,14 +689,14 @@ Reference implementation + (define (traverse s) + (lazy (traverse (cdr (force s))))) + +-;(force (traverse (from 0))) ;==> bounded space ++;(force (traverse (from 0))) ;==> bounded space + + ;========================================================================= + ; Leak test 4: Safely traversing infinite stream + ; while pointer to head of result exists. + + (define s (traverse (from 0))) +-;(force s) ;==> bounded space ++;(force s) ;==> bounded space + + ;========================================================================= + ; Convenient list deconstructor used below. +@@ -689,7 +726,7 @@ Reference implementation + + ;(force (stream-filter (lambda (n) (= n 10000000000)) + ; (from 0))) +- ;==> bounded space ++ ;==> bounded space + + ;======================================================================== + ; Leak test 6: Another long traversal should run in bounded space. +@@ -710,10 +747,10 @@ Reference implementation + ; Check that evenness is correctly implemented - should terminate: + + (force (stream-ref (stream-filter zero? (from 0)) +- 0)) ;==> 0 ++ 0)) ;==> 0 + + (define s (stream-ref (from 0) 100000000)) +-;(force s) ;==> bounded space ++;(force s) ;==> bounded space + + ;====================================================================== + ; Leak test 7: Infamous example from SRFI 40. +@@ -725,31 +762,33 @@ Reference implementation + 3)) + + (force (times3 7)) +-;(force (times3 100000000)) ;==> bounded space ++;(force (times3 100000000)) ;==> bounded space + + </pre> + +- <H1>References</H1> +- ++ <h2>References</h2> ++<p> + [Wad98] + Philip Wadler, Walid Taha, and David MacQueen. + <em>How to add laziness to a strict language, without even being odd</em>, + Workshop on Standard ML, Baltimore, September 1998 ++</p> + <p> + [Jon92] + Richard Jones. <em>Tail recursion without space leaks</em>, Journal of Functional Programming, 2(1):73-79, January 1992 ++</p> + <p> + [Fee97] + Marc Feeley, James S. Miller, Guillermo J. Rozas, Jason A. Wilson, + <em> Compiling Higher-Order Languages into Fully Tail-Recursive Portable C</em>, + Rapport technique 1078, département d'informatique et r.o., Université de Montréal, août 1997. ++</p> + + + ++ <h2>Copyright</h2> + +- <H1>Copyright</H1> +- +-<p>Copyright (C) André van Tonder (2003). All Rights Reserved.</p> ++<p>Copyright (C) André van Tonder (2003). All Rights Reserved.</p> + + <p> + Permission is hereby granted, free of charge, to any person obtaining +@@ -774,12 +813,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> ++ <hr /> + <address>Author: <a href="mailto:andre@het.brown.edu">André van Tonder</a></address> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Francisco Solsona</a></address> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + <!-- Created: Fri Sep 19 17:55:00 EST 2002 --> + <!-- hhmts start --> +-Last modified: Tue Dec 30 11:21:21 CST 2003 ++Last modified: Sun Jan 28 13:40:19 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-48.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-48.html +index e73f4aa..f60c008 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-48.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-48.html +@@ -1,90 +1,115 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-48 ┃ ++┃ Commit: 2183cf51cf91192667d871e7fc9a9fa6dfa63f7e ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 48: Intermediate Format Strings</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> +- +-SRFI 48: Intermediate Format Strings +- +-<H1>Author</H1> +- +-Ken Dickey +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each status that a +-SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access +-previous messages via +-<a href="http://srfi.schemers.org/srfi-48/mail-archive/maillist.html"> +-the archive of the mailing list</a>. +- +- <p><ul> +- <li>Received: 2003/11/24</li> +- <li>Draft: 2003/11/25-2004/02/25</li> +- <li>Revised: 2003/12/04</li> +- <li>Revised: 2003/12/28</li> +- <li>Final: 2004/03/02</li> +- <li>Revised: 2005/06/01</li> +- </ul></p> +- +-<H1>Abstract</H1> +- +-This document specifies Format Strings, a method of interpreting a Scheme string which contains a ++<h1>SRFI 48: Intermediate Format Strings</h1> ++ ++<p>by Ken Dickey</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 48 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-48/srfi-48.html">https://srfi.schemers.org/srfi-48/srfi-48.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+48+at+srfi+dotschemers+dot+org">srfi-48@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-48">archive</a>.</p> ++<ul> ++ <li>Received: 2003-11-24</li> ++ <li>Draft: 2003-11-25--2004-02-25</li> ++ <li>Revised: 2003-12-04</li> ++ <li>Revised: 2003-12-28</li> ++ <li>Final: 2004-03-02</li> ++ <li>Revised: 2005-06-01</li> ++ <li><a href="https://srfi.schemers.org/srfi-48/errata.html">Errata</a></li> ++ <li><b>post-finalization note</b>: On 2020-03-18, Per Bothner ++ began an email ++ <a href="https://srfi-email.schemers.org/srfi-48/msg/13511377/">discussion</a> ++ of the proper semantics of SRFI 48's freshline ++ (<code>~&</code>) directive, suggesting a change when it ++ is not known whether the previous character was a newline. ++ This is not an error in the SRFI, but deviation from it that ++ Per recommends. SRFI 48 author Ken Dickey responded with a ++ patch to the sample implementation that could be used to ++ implement Per's change, if desired.</li></ul> ++ ++<h2>Abstract</h2> ++<p> ++This document specifies Format Strings, a method of interpreting a Scheme string which contains a + number of format directives that are replaced with other string data according to the semantics of each directive. +-This SRFI extends <a href="http://srfi.schemers.org/srfi-28/srfi-28.html">SRFI-28</a> in being more generally useful but is less general than +-advanced format strings in that it does not allow, aside from ~F, for controlled positioning of text within fields. ++This SRFI extends <a href="srfi-28.html">SRFI-28</a> in being more generally useful but is less general than ++advanced format strings in that it does not allow, aside from ~F, for controlled positioning of text within fields. ++</p> + +-<H1>Issues</H1> ++<h2>Issues</h2> + +-<P> +-Some may disagree with specific escape options or return values. +-For those who desire complex options as implemented by SLIB +-or Common Lisp's FORMAT, an upwards compatible ++<p> ++Some may disagree with specific escape options or return values. ++For those who desire complex options as implemented by SLIB ++or Common Lisp's FORMAT, an upwards compatible + "Advanced Format" SRFI should be proposed. +-</P><P> +-In particular, the reference implementation given here does not accept numeric arguments +-(aside from ~F). +-Hence it does <b>not</b> support <a href="http://srfi.schemers.org/srfi-29/srfi-29.html">SRFI-29</a>. +-</P><P> +-It is highly desirable that baseline library code be small, attempt to +-eliminiate heap allocation and bound stack usage. ++</p><p> ++In particular, the reference implementation given here does not accept numeric arguments ++(aside from ~F). ++Hence it does <b>not</b> support <a href="srfi-29.html">SRFI-29</a>. ++</p><p> ++It is highly desireable that baseline library code be small, attempt to ++eliminiate heap allocation and bound stack usage. + This is especially important in embedded systems. +-This can be accomplished by writing directly to a port, +-rather than a string, by not supporting ~W or ~F, ++This can be accomplished by writing directly to a port, ++rather than a string, by not supporting ~W or ~F, + and by replacing +-<I>(display (number->string n r) p)</I> with a carefully written +-<I>(display:number->string n r p)</I> which does not build intermediate strings. +-</P><P> +-As this is <B>intermediate</B> format, it was felt that ~F and ~W are too highly useful to elide. ++<i>(display (number->string n r) p)</i> with a carefully written ++<i>(display:number->string n r p)</i> which does not build intermediate strings. ++</p><p> ++As this is <b>intermediate</b> format, it was felt that ~F and ~W are too highly useful to elide. + The ~H option is helpful to users, allows for programattic query, and makes clear which format directives are supported. +-</P> ++</p> + +-<H1>Rationale</H1> +-<P> ++<h2>Rationale</h2> ++<p> + Inheriting from MacLisp, nearly all Lisp and Scheme implementations support some form of +-FORMAT function with support for various numbers of format directives. +-By agreeing to the options here, we raise the bar for portable code. +-</P><P> ++FORMAT function with support for various numbers of format directives. ++By agreeing to the options here, we raise the bar for portable code. ++</p><p> + The reference implementation is R5RS compliant and easy to port. +-In not requiring advanced features (aside from ~W and ~F) small implementations are possible. +-E.g. the reference code does not use side effects (assignment) and is less than +-a third the source size of the latest SLIB implementation of FORMAT ++In not requiring advanced features (aside from ~W and ~F) small implementations are possible. ++E.g. the reference code does not use side effects (assignment) and is less than ++a third the source size of the latest SLIB implementation of FORMAT + (less than a tenth if ~F support is elided). +-</P><P> +-The optional <i>port</i> argument allows for compatibility with older code +-written for, e.g. scheme48, MIT Scheme, T, et cetera, which required a port argument. ++</p><p> ++The optional <i>port</i> argument allows for compatibility with older code ++written for, e.g. scheme48, MIT Scheme, T, et cetera, which required a port argument. + It is also useful in cases where a synoptic + implementation of Scheme and CommonLisp is maintained. +-</P> ++</p> + +-<H1>Specification</H1> ++<h2 id="format">Specification</h2> + +- <a name="format"><b><tt>format</tt></b></a> <tt><i>[port] format-string [obj ...]</i> </tt> ++ <b><tt>format</tt></b> <tt><i>[port] format-string [obj ...]</i> </tt> + + <blockquote> + <p>Accepts a format template (a Scheme String), and +@@ -93,22 +118,22 @@ implementation of Scheme and CommonLisp is maintained. + on the semantics of the format directive encountered. Each directive + may consume one obj. It is an error if fewer or more obj values are + provided than format directives that require them.</p> +- +- <p>When a <i>port</i> is specified it must be either an output port or ++ ++ <p>When a <i>port</i> is specified it must be either an output port or + a boolean. If an output-port is specified, the formatted output is + output into that port. If the port argument is #t, output is to the + current-output-port. If the port is #f or no port is specified, the +- output is returned as a string. If the port is specified and is #t ++ output is returned as a string. If the port is specified and is #t + or an output-port, the result of the format function is unspecified.</p> +- +- <p>It is unspecified which encoding is used (e.g. ASCII, EBCDIC, UNICODE). +- A given implementation must specify which encoding is used. ++ ++ <p>It is unspecified which encoding is used (e.g. ASCII, EBCDIC, UNICODE). ++ A given implementation must specify which encoding is used. + The implementation may or may not allow the encoding to be selected or changed.</p> +- +- <p>It is an error if an format directive consumes an <i>obj</i> argument and ++ ++ <p>It is an error if an format directive consumes an <i>obj</i> argument and + that argument does not + confirm to a required type as noted in the table below.</p> +- ++ + <p>It is permissible, but highly discouraged, to implement pretty-print as + <i>(define pretty-print write)</i>.</p> + +@@ -117,14 +142,14 @@ implementation of Scheme and CommonLisp is maintained. + are case-independent, i.e. upper and lower case characters + are interpreted the same. Each directive + code's meaning is described in the following table:</p> +- ++ + <table> + <tr> + <td><b>DIRECTIVE</b></td> + <td><b>MNEMONIC</b></td> + <td><b>ACTION</b></td> +-<td><b>CONSUMES?</b><td> +-</tr> ++<td><b>CONSUMES?</b></td><td> ++</td></tr> + <tr> + <td>~a</td> + <td>Any</td> +@@ -142,7 +167,7 @@ implementation of Scheme and CommonLisp is maintained. + <td>WriteCircular</td> + <td>(write-with-shared-structure obj) like ~s, but handles recursive structures</td> + <td>yes</td> +-</tr> ++</tr> + <tr> + <td>~d</td> + <td>Decimal</td> +@@ -188,13 +213,13 @@ implementation of Scheme and CommonLisp is maintained. + <tr> + <td>~K</td> + <td>Indirection</td> +- <td>the same as ~? for backward compatibility with some existing implementations</td> ++ <td>the same as ~? for backward compatability with some existing implementations</td> + <td>yes</td> + </tr> + <tr> + <td>~[w[,d]]F</td> + <td>Fixed</td> +- <td>~w,dF outputs a number with width w and d digits after the decimal; ++ <td>~w,dF outputs a number with width w and d digits after the decimal; + ~wF outputs a string or number with width w.</td> + <td>yes</td> + </tr> +@@ -217,7 +242,7 @@ implementation of Scheme and CommonLisp is maintained. + <td>no</td> + </tr> + <tr> +- <td>~&</td> ++ <td>~&</td> + <td>Freshline</td> + <td>output a newline character if it is known that the previous output was not a newline</td> + <td>no</td> +@@ -237,42 +262,53 @@ synopsis for each format directive, starting with the directive (e.g. "~t") + <td>no</td> + </tr> + </table> +-<br> ++<br /> + <p> + The <b>~F</b>, fixed format, directive requires some elucidation. + </p><p> +- <b>~wF</b> is useful for strings or numbers. Where the string (or number->string ++ <b>~wF</b> is useful for strings or numbers. Where the string (or number->string + of the number) has fewer characters than the integer width w, the string is + padded on the left with space characters. +- </p><p> ++ </p> ++ <p> + <b>~w,dF</b> is typically used only on numbers. For strings, the <b>d</b> + specifier is ignored. For numbers, the integer <b>d</b> specifies the number + of decimal digits after the decimal place. Both <b>w</b> and <b>d</b> must be + zero or positive. +- </p><p> ++ </p> ++ <p> + If <b>d</b> is specified, the number is processed + as if added to 0.0, i.e. it is converted to an inexact value. ++ </p> + <pre>(format "~8,2F" 1/3) => " 0.33"</pre> ++ <p> + If no <b>d</b> is specified, the number is <i>not</i> coerced to inexact. +- <pre>(format "~6F" 32) => " 32"</pre> +- Digits are padded to the right with zeros +- <pre>(format "~8,2F" 32) => " 32.00"</pre> +- If the number it too large to fit in the width specified, ++ </p> ++ <pre>(format "~6F" 32) => " 32"</pre> ++ <p> ++ Digits are padded to the right with zeros ++ </p> ++ <pre>(format "~8,2F" 32) => " 32.00"</pre> ++ <p> ++ If the number it too large to fit in the width specified, + a string longer than the width is returned +- <pre>(format "~1,2F" 4321) => "4321.00"</pre> ++ </p> ++ <pre>(format "~1,2F" 4321) => "4321.00"</pre> ++ <p> + If the number is complex, <b>d</b> is applied to both real and imaginal parts ++ </p> + <pre>(format "~1,2F" (sqrt -3.9)) => "0.00+1.97i"</pre> +- </p><p> +- For very large or very small numbers, the point where exponential notation ++ <p> ++ For very large or very small numbers, the point where exponential notation + is used is implementation defined. ++ </p> + <pre>(format "~8F" 32e5) => " 3.2e6" or "3200000.0"</pre> +- </p> + </blockquote> +-<br> +- <h2>Examples</h2> ++<br /> ++ <h3>Examples</h3> + <pre> + (format "~h") +-; => ++; => + "(format [<port>] <format-string> [<arg>...]) -- <port> is #t, #f or an output-port + OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + ~H [Help] output this text +@@ -281,7 +317,7 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + ~~ [tilde] output a tilde + ~T [Tab] output a tab character + ~% [Newline] output a newline character +-~& [Freshline] output a newline character if the previous output was not a newline ++~& [Freshline] output a newline character if the previous output was not a newline + ~D [Decimal] the arg is a number which is output in decimal radix + ~X [heXadecimal] the arg is a number which is output in hexdecimal radix + ~O [Octal] the arg is a number which is output in octal radix +@@ -298,7 +334,7 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + ; => "Hello, World!" + + (format "Error, list is too short: ~s" '(one "two" 3)) +-; => "Error, list is too short: (one \"two\" 3))" ++; => "Error, list is too short: (one \"two\" 3)" + + (format "test me") + ; => "test me" +@@ -313,8 +349,8 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + (format "~a ~? ~a" 'a "~s" '(new) 'test) + ; =>"a new test" + +-(format #f "~&1~&~&2~&~&~&3~%") +-; => ++(format #f "~&1~&~&2~&~&~&3~%") ++; => + " + 1 + 2 +@@ -322,8 +358,8 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + " + + (format #f "~a ~? ~a ~%" 3 " ~s ~s " '(2 2) 3) +-; => +-"3 2 2 3 ++; => ++"3 2 2 3 + " + + (format "~w" (let ( (c '(a b c)) ) (set-cdr! (cddr c) c) c)) +@@ -356,34 +392,45 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + (format "~8,3F" "foo") + ; => " foo" + +-(format "~a~a~&" (list->string (list #\newline)) "") ++(format "~a~a~&" (list->string (list #\newline)) "") + ; => + " + " + + </pre> +- + + +-<H1>Implementation</H1> ++ ++<h2>Implementation</h2> + + The implementation below requires SRFI-6 (Basic string ports), +- SRFI-23 (Error reporting mechanism) and +- SRFI-38 (External Representation for Data With Shared Structure). <br> +- ++ SRFI-23 (Error reporting mechanism) and ++ SRFI-38 (External Representation for Data With Shared Structure). <br /> ++ + + <pre> + + ;; IMPLEMENTATION DEPENDENT options + +-(define ascii-tab (integer->char 9)) ;; NB: assumes ASCII encoding ++(define ascii-tab (integer->char 9)) ;; NB: assumes ASCII encoding + (define dont-print (if (eq? #t #f) 1)) +-;;(define DONT-PRINT (string->symbol "")) ++;;(define DONT-PRINT (string->symbol "")) + ;;(define DONT-PRINT (void)) + ;;(define DONT-PRINT #!void) + (define pretty-print write) ; ugly but permitted + ;; (require 'srfi-38) ;; write-with-shared-structure + ++;; Following three procedures are used by format ~F . ++;; 'inexact-number->string' determines whether output is fixed-point ++;; notation or exponential notation. In the current definition, ++;; the notation depends on the implementation of 'number->string'. ++;; 'exact-number->string' is expected to output only numeric characters ++;; (not including such as '#', 'e', '.', '/') if the input is an positive ++;; integer or zero. ++;; 'real-number->string' is used when the digits of ~F is not specified. ++(define (inexact-number->string x) (number->string (exact->inexact x))) ++(define (exact-number->string x) (number->string (inexact->exact x))) ++(define (real-number->string x) (number->string x)) + + ;; FORMAT + (define (format . args) +@@ -393,7 +440,7 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + ) + ((string? (car args)) + (apply format (cons #f args))) +- ((< (length args) 2) ++ ((< (length args) 2) + (error (format #f "FORMAT: too few arguments ~s" (cons 'format args))) + ) + (else +@@ -401,20 +448,20 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + (format-string (cadr args)) + (args (cddr args)) + ) +- (letrec ( (port ++ (letrec ( (port + (cond ((output-port? output-port) output-port) +- ((eq? output-port #t) (current-output-port)) +- ((eq? output-port #f) (open-output-string)) ++ ((eq? output-port #t) (current-output-port)) ++ ((eq? output-port #f) (open-output-string)) + (else (error + (format #f "FORMAT: bad output-port argument: ~s" + output-port))) + ) ) +- (return-value +- (if (eq? output-port #f) ;; if format into a string ++ (return-value ++ (if (eq? output-port #f) ;; if format into a string + (lambda () (get-output-string port)) ;; then return the string + (lambda () dont-print)) ;; else do something harmless +- ) +- ) ++ ) ++ ) + + (define (string-index str c) + (let ( (len (string-length str)) ) +@@ -432,7 +479,7 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + (define (compose-with-digits digits pre-str frac-str exp-str) + (let ( (frac-len (string-length frac-str)) ) + (cond +- ((< frac-len digits) ;; grow frac part, pad with zeros ++ ((< frac-len digits) ;; grow frac part, pad with zeros + (string-append pre-str "." + frac-str (make-string (- digits frac-len) #\0) + exp-str) +@@ -443,28 +490,39 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + exp-str) + ) + (else ;; must round to shrink it +- (let* ( (first-part (substring frac-str 0 digits)) ++ (let* ( (minus-flag (and (> (string-length pre-str) 0) ++ (char=? (string-ref pre-str 0) #\-))) ++ (pre-str* (if minus-flag ++ (substring pre-str 1 (string-length pre-str)) ++ pre-str)) ++ (first-part (substring frac-str 0 digits)) + (last-part (substring frac-str digits frac-len)) + (temp-str +- (number->string +- (round (string->number +- (string-append first-part "." last-part))))) +- (dot-pos (string-index temp-str #\.)) +- (carry? +- (and (> dot-pos digits) +- (> (round (string->number +- (string-append "0." frac-str))) +- 0))) +- (new-frac +- (substring temp-str 0 digits)) ++ (string-grow ++ (exact-number->string ++ (round (string->number ++ (string-append pre-str* first-part "." last-part)))) ++ digits ++ #\0)) ++ (temp-len (string-length temp-str)) ++ (new-pre (substring temp-str 0 (- temp-len digits))) ++ (new-frac (substring temp-str (- temp-len digits) temp-len)) + ) + (string-append +- (if carry? (number->string (+ 1 (string->number pre-str))) pre-str) ++ (if minus-flag "-" "") ++ (if (string=? new-pre "") ++ ;; check if the system displays integer part of numbers ++ ;; whose absolute value is 0 < x < 1. ++ (if (and (string=? pre-str* "") ++ (> digits 0) ++ (not (= (string->number new-frac) 0))) ++ "" "0") ++ new-pre) + "." + new-frac + exp-str))) + ) ) ) +- ++ + (define (format-fixed number-or-string width digits) ; returns a string + (cond + ((string? number-or-string) +@@ -485,44 +543,43 @@ OPTION [MNEMONIC] DESCRIPTION -- This implementation Assumes ASCII Text Encoding + #\space) + ) + (digits +- (let* ( (num-str (number->string (exact->inexact real))) ++ (let* ( (num-str (inexact-number->string real)) + (dot-index (string-index num-str #\.)) + (exp-index (string-index num-str #\e)) + (length (string-length num-str)) + (pre-string +- (cond +- (exp-index +- (if dot-index +- (substring num-str 0 dot-index) +- (substring num-str 0 (+ exp-index 1))) +- ) +- (dot-index +- (substring num-str 0 dot-index) +- ) +- (else +- num-str)) ++ (if dot-index ++ (substring num-str 0 dot-index) ++ (if exp-index ++ (substring num-str 0 exp-index) ++ num-str)) + ) + (exp-string +- (if exp-index (substring num-str exp-index length) "") ++ (if exp-index ++ (substring num-str exp-index length) ++ "") + ) + (frac-string +- (if exp-index +- (substring num-str (+ dot-index 1) exp-index) +- (substring num-str (+ dot-index 1) length)) ++ (if dot-index ++ (if exp-index ++ (substring num-str (+ dot-index 1) exp-index) ++ (substring num-str (+ dot-index 1) length)) ++ "") + ) + ) +- (string-grow +- (if dot-index ++ ;; check +inf.0, -inf.0, +nan.0, -nan.0 ++ (if (string-index num-str #\n) ++ (string-grow num-str width #\space) ++ (string-grow + (compose-with-digits digits + pre-string + frac-string + exp-string) +- (string-append pre-string exp-string)) +- width +- #\space) ++ width ++ #\space)) + )) + (else ;; no digits +- (string-grow (number->string real) width #\space))) ++ (string-grow (real-number->string real) width #\space))) + )) + (else + (error +@@ -539,7 +596,7 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + ~~ [tilde] output a tilde + ~T [Tab] output a tab character + ~% [Newline] output a newline character +-~& [Freshline] output a newline character if the previous output was not a newline ++~& [Freshline] output a newline character if the previous output was not a newline + ~D [Decimal] the arg is a number which is output in decimal radix + ~X [heXadecimal] the arg is a number which is output in hexdecimal radix + ~O [Octal] the arg is a number which is output in octal radix +@@ -557,25 +614,25 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + (if (null? args) + (error "FORMAT: too few arguments" )) + ) +- ++ + (define (format-help format-strg arglist) +- ++ + (letrec ( + (length-of-format-string (string-length format-strg)) +- +- (anychar-dispatch +- (lambda (pos arglist last-was-newline) +- (if (>= pos length-of-format-string) +- arglist ; return unused args +- (let ( (char (string-ref format-strg pos)) ) +- (cond +- ((eqv? char #\~) +- (tilde-dispatch (+ pos 1) arglist last-was-newline)) +- (else +- (write-char char port) +- (anychar-dispatch (+ pos 1) arglist #f) +- )) +- )) ++ ++ (anychar-dispatch ++ (lambda (pos arglist last-was-newline) ++ (if (>= pos length-of-format-string) ++ arglist ; return unused args ++ (let ( (char (string-ref format-strg pos)) ) ++ (cond ++ ((eqv? char #\~) ++ (tilde-dispatch (+ pos 1) arglist last-was-newline)) ++ (else ++ (write-char char port) ++ (anychar-dispatch (+ pos 1) arglist #f) ++ )) ++ )) + )) ; end anychar-dispatch + + (has-newline? +@@ -587,90 +644,90 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + last-was-newline + (eqv? #\newline (string-ref whatever (- len 1))))))) + )) ; end has-newline? +- +- (tilde-dispatch +- (lambda (pos arglist last-was-newline) +- (cond +- ((>= pos length-of-format-string) ++ ++ (tilde-dispatch ++ (lambda (pos arglist last-was-newline) ++ (cond ++ ((>= pos length-of-format-string) + (write-char #\~ port) ; tilde at end of string is just output + arglist ; return unused args +- ) +- (else +- (case (char-upcase (string-ref format-strg pos)) ++ ) ++ (else ++ (case (char-upcase (string-ref format-strg pos)) + ((#\A) ; Any -- for humans + (require-an-arg arglist) + (let ( (whatever (car arglist)) ) + (display whatever port) +- (anychar-dispatch (+ pos 1) +- (cdr arglist) ++ (anychar-dispatch (+ pos 1) ++ (cdr arglist) + (has-newline? whatever last-was-newline)) + )) + ((#\S) ; Slashified -- for parsers + (require-an-arg arglist) + (let ( (whatever (car arglist)) ) +- (write whatever port) +- (anychar-dispatch (+ pos 1) +- (cdr arglist) +- (has-newline? whatever last-was-newline)) ++ (write whatever port) ++ (anychar-dispatch (+ pos 1) ++ (cdr arglist) ++ (has-newline? whatever last-was-newline)) + )) + ((#\W) + (require-an-arg arglist) + (let ( (whatever (car arglist)) ) + (write-with-shared-structure whatever port) ;; srfi-38 +- (anychar-dispatch (+ pos 1) +- (cdr arglist) ++ (anychar-dispatch (+ pos 1) ++ (cdr arglist) + (has-newline? whatever last-was-newline)) +- )) ++ )) + ((#\D) ; Decimal + (require-an-arg arglist) +- (display (number->string (car arglist) 10) port) +- (anychar-dispatch (+ pos 1) (cdr arglist) #f) +- ) ++ (display (number->string (car arglist) 10) port) ++ (anychar-dispatch (+ pos 1) (cdr arglist) #f) ++ ) + ((#\X) ; HeXadecimal + (require-an-arg arglist) +- (display (number->string (car arglist) 16) port) +- (anychar-dispatch (+ pos 1) (cdr arglist) #f) +- ) ++ (display (number->string (car arglist) 16) port) ++ (anychar-dispatch (+ pos 1) (cdr arglist) #f) ++ ) + ((#\O) ; Octal + (require-an-arg arglist) +- (display (number->string (car arglist) 8) port) +- (anychar-dispatch (+ pos 1) (cdr arglist) #f) +- ) ++ (display (number->string (car arglist) 8) port) ++ (anychar-dispatch (+ pos 1) (cdr arglist) #f) ++ ) + ((#\B) ; Binary + (require-an-arg arglist) +- (display (number->string (car arglist) 2) port) +- (anychar-dispatch (+ pos 1) (cdr arglist) #f) +- ) ++ (display (number->string (car arglist) 2) port) ++ (anychar-dispatch (+ pos 1) (cdr arglist) #f) ++ ) + ((#\C) ; Character + (require-an-arg arglist) +- (write-char (car arglist) port) +- (anychar-dispatch (+ pos 1) (cdr arglist) (eqv? (car arglist) #\newline)) +- ) +- ((#\~) ; Tilde +- (write-char #\~ port) +- (anychar-dispatch (+ pos 1) arglist #f) +- ) +- ((#\%) ; Newline +- (newline port) +- (anychar-dispatch (+ pos 1) arglist #t) ++ (write-char (car arglist) port) ++ (anychar-dispatch (+ pos 1) (cdr arglist) (eqv? (car arglist) #\newline)) ++ ) ++ ((#\~) ; Tilde ++ (write-char #\~ port) ++ (anychar-dispatch (+ pos 1) arglist #f) + ) +- ((#\&) ; Freshline ++ ((#\%) ; Newline ++ (newline port) ++ (anychar-dispatch (+ pos 1) arglist #t) ++ ) ++ ((#\&) ; Freshline + (if (not last-was-newline) ;; (unless last-was-newline .. + (newline port)) + (anychar-dispatch (+ pos 1) arglist #t) + ) +- ((#\_) ; Space +- (write-char #\space port) ++ ((#\_) ; Space ++ (write-char #\space port) ++ (anychar-dispatch (+ pos 1) arglist #f) ++ ) ++ ((#\T) ; Tab -- IMPLEMENTATION DEPENDENT ENCODING ++ (write-char ascii-tab port) + (anychar-dispatch (+ pos 1) arglist #f) +- ) +- ((#\T) ; Tab -- IMPLEMENTATION DEPENDENT ENCODING +- (write-char ascii-tab port) +- (anychar-dispatch (+ pos 1) arglist #f) +- ) ++ ) + ((#\Y) ; Pretty-print + (pretty-print (car arglist) port) ;; IMPLEMENTATION DEPENDENT + (anychar-dispatch (+ pos 1) (cdr arglist) #f) +- ) ++ ) + ((#\F) + (require-an-arg arglist) + (display (format-fixed (car arglist) 0 #f) port) +@@ -682,7 +739,7 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + (d-digits '()) + (in-width? #t) + ) +- (if (>= index length-of-format-string) ++ (if (>= index length-of-format-string) + (error + (format "FORMAT: improper numeric format directive in ~s" format-strg)) + (let ( (next-char (string-ref format-strg index)) ) +@@ -698,11 +755,11 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + (cons next-char d-digits) + in-width?)) + ) +- ((char=? next-char #\F) +- (let ( (width (string->number (list->string (reverse w-digits)))) ++ ((char=? (char-upcase next-char) #\F) ++ (let ( (width (string->number (list->string (reverse w-digits)))) + (digits (if (zero? (length d-digits)) + #f +- (string->number (list->string (reverse d-digits))))) ++ (string->number (list->string (reverse d-digits))))) + ) + (display (format-fixed (car arglist) width digits) port) + (anychar-dispatch (+ index 1) (cdr arglist) #f)) +@@ -721,7 +778,7 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + )) + ((#\? #\K) ; indirection -- take next arg as format string + (cond ; and following arg as list of format args +- ((< (length arglist) 2) ++ ((< (length arglist) 2) + (error + (format "FORMAT: less arguments than specified for ~~?: ~s" arglist)) + ) +@@ -737,31 +794,31 @@ OPTION [MNEMONIC] DESCRIPTION -- Implementation Assumes ASCII Text Enc + (display documentation-string port) + (anychar-dispatch (+ pos 1) arglist #t) + ) +- (else ++ (else + (error (format "FORMAT: unknown tilde escape: ~s" + (string-ref format-strg pos)))) + ))) +- )) ; end tilde-dispatch +- ) ; end letrec +- +- ; format-help main +- (anychar-dispatch 0 arglist #f) +- )) ; end format-help +- ++ )) ; end tilde-dispatch ++ ) ; end letrec ++ ++ ; format-help main ++ (anychar-dispatch 0 arglist #f) ++ )) ; end format-help ++ + ; format main + (let ( (unused-args (format-help format-string args)) ) + (if (not (null? unused-args)) + (error + (format "FORMAT: unused arguments ~s" unused-args))) + (return-value)) +- ++ + )) ; end letrec, if + ))) ; end format + + </pre> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Kenneth A Dickey (2003). All Rights Reserved.</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining +@@ -786,12 +843,12 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> ++ <hr /> + <address>Author: <a href="mailto:Ken.Dickey@allvantage.com">Ken Dickey</a></address> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Francisco Solsona</a></address> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Wed Jun 01 10:40:09 CST 2005 ++Last modified: Sun Jan 28 13:40:35 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-54.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-54.html +index da1c5a7..1ff3420 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-54.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-54.html +@@ -1,32 +1,57 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html><head><title>SRFI 54: Formatting</title></head><body> +- +-<h1>Title</h1> +- +-Formatting +- +-<h1>Author</h1> +- +-Joo ChurlSoo +- +-<h1>Status</h1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access the discussion via <a href="http://srfi.schemers.org/srfi-54/mail-archive/maillist.html">the archive of the mailing list</a>. +-<p></p><ul> +- +-<li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.1">2004/03/28</a></li> +-<li>Draft: 2004/03/22-2004/06/22</li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.3">2004/04/07</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.4">2004/04/12</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.6">2004/04/20</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.7">2004/04/29</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.txt?rev=1.8">2004/05/27</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.html?rev=1.9">2004/06/09</a></li> +-<li>Reference implementation fix: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-54/srfi-54.html?rev=1.10">2006/01/20</a></li> +-<li>Final: 2004/06/24</li> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-54 ┃ ++┃ Commit: 57a21f9afb4682f8cb892848be12868794835ec6 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 54: Formatting</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> ++ ++ <body> ++ ++<h1>SRFI 54: Formatting</h1> ++ ++<p>by Joo ChurlSoo</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 54 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-54/srfi-54.html">https://srfi.schemers.org/srfi-54/srfi-54.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+54+at+srfi+dotschemers+dot+org">srfi-54@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-54">archive</a>.</p> ++<ul> ++ ++<li>Received: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.1.txt">2004-03-28</a></li> ++<li>Draft: 2004-03-22--2004-06-22</li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.3.txt">2004-04-07</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.4.txt">2004-04-12</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.6.txt">2004-04-20</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.7.txt">2004-04-29</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.8.txt">2004-05-27</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.9.html">2004-06-09</a></li> ++<li>Reference implementation fix: <a href="https://srfi.schemers.org/srfi-54/srfi-54-1.10.html">2006-01-20</a></li> ++<li>Final: 2004-06-24</li> + </ul> + +-<h1>Abstract</h1> ++<h2>Abstract</h2> + + + <p>This SRFI introduces the CAT procedure that converts any object to a string. +@@ -34,7 +59,7 @@ It takes one object as the first argument and accepts a variable number of + optional arguments, unlike the procedure called FORMAT.</p> + + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + + + <p>It is difficult to gain a complete consensus for the design of a generic +@@ -47,7 +72,7 @@ interface. With the concept of free sequencing, the CAT procedure is then + defined, not to process optional arguments with default values, but to process + default values with optional arguments.</p> + +-<h1>Issues</h1> ++<h2>Issues</h2> + + + <p>In converting a number to a string, it has not been tried to uniformly express +@@ -58,7 +83,7 @@ have a decimal point. An inexact sign is prefixed to the resulting string in + addition to an radix sign when an inexact number is converted to a + non-decimal.</p> + +-<h1>Specification</h1> ++<h2>Specification</h2> + + <dl> + <dt> +@@ -67,66 +92,24 @@ non-decimal.</p> + [<writer$>] [<pipe$>] [<take$>] + [<converter*>] [<width*>] [<char*>] [<port*>] [<string*>] ...) + </code></dt> +-<dd><suffix%>: effective only for the number type of <object>.<br> +- <suffix$>: effective for all types except the number type of <object>.<br> ++<dd><suffix%>: effective only for the number type of <object>.<br /> ++ <suffix$>: effective for all types except the number type of <object>.<br /> + <suffix*>: effective for all types of <object>.</dd> + <dd><object> is any Scheme object.</dd> + <dd><exactness> is a symbol: exact or inexact.</dd> +-<dd><radix> is a symbol: binary, octal, decimal, or hexadecimal.<br> +- Each radix sign except decimal is prefixed to the resulting string.<br> ++<dd><radix> is a symbol: binary, octal, decimal, or hexadecimal.<br /> ++ Each radix sign except decimal is prefixed to the resulting string.<br /> + The default value is decimal.</dd> +-<dd>If <sign> is a symbol that takes the form of 'sign, and +-<object> is a positive number without a positive sign, the +-positive sign is prefixed to the resulting string.</dd> +-<dd><precision> is an inexact integer whose absolute value +-specifies the number of decimal digits after a decimal point. If +-<precision> is a non-negative integer, an exact sign is prefixed +-to the resulting string as needed.</dd> +-<dd><separator> is a list whose first element is a character +-serving as a separator and second element is a positive exact integer. +-If the integer is n, the resulting string is separated in every +-n-characters of the resulting string. When the integer is omitted, the +-default value is 3.</dd> +-<dd><writer> is a procedure of two arguments; <object> and +-a string port. It writes <object> to the string port. The default +-value of <writer> is varied according to the type of +-<object>. When <object> is a self-evaluating constant, it +-becomes equivalent to DISPLAY procedure, otherwise, it becomes WRITE +-procedure. If you want any objects to be displayed in your own way, you +-have to define your own <writer>. Otherwise, they are displayed +-simply in their evaluated forms.</dd> +-<dd><pipe> is a list which is composed of one or more procedures. +-Each procedure takes at least one string argument and returns a string. +-One procedure connects with another as a pipe.</dd> +-<dd><take> is a list whose elements are two exact integers; n and +-m, and the absolute values of n and m are N and M, respectively. First, +-the resulting string takes from the left n-characters, if it is +-non-negative, or all the characters but N-characters, if negative. +-Second, it takes from the right m-characters, if it is non-negative, or +-all the characters but M-characters, if negative. Then, it concatenates +-two set of characters taken. The second element can be omitted. If +-omitted, the default value is 0.</dd> +-<dd><converter> is a pair whose car value is a predicate +-procedure that checks whether <object> satisfies it, and cdr +-value is a procedure that takes the <object> as an argument and +-returns a string. When <object> satisfies the predicate +-procedure, all optional arguments are ineffective except <width>, +-<char>, <port>, and <string>.</dd> +-<dd><width> is an exact integer whose absolute value specifies +-the width of the resulting string. When the resulting string has fewer +-characters than the absolute value of <width>, it is placed +-rightmost with the rest being padded with <char>s, if +-<width> is positive, or it is placed leftmost with the rest being +-padded with <char>s, if <width> is negative. On the other +-hand, when the resulting string has more characters than the absolute +-value of <width>, the <width> is ignored. The default value +-is 0.</dd> ++<dd>If <sign> is a symbol that takes the form of 'sign, and <object> is a positive number without a positive sign, the positive sign is prefixed to the resulting string.</dd> ++<dd><precision> is an inexact integer whose absolute value specifies the number of decimal digits after a decimal point. If <precision> is a non-negative integer, an exact sign is prefixed to the resulting string as needed.</dd> ++<dd><separator> is a list whose first element is a character serving as a separator and second element is a positive exact integer. If the integer is n, the resulting string is separated in every n-characters of the resulting string. When the integer is omitted, the default value is 3.</dd> ++<dd><writer> is a procedure of two arguments; <object> and a string port. It writes <object> to the string port. The default value of <writer> is varied according to the type of <object>. When <object> is a self-evaluating constant, it becomes equivalent to DISPLAY procedure, otherwise, it becomes WRITE procedure. If you want any objects to be displayed in your own way, you have to define your own <writer>. Otherwise, they are displayed simply in their evaluated forms.</dd> ++<dd><pipe> is a list which is composed of one or more procedures. Each procedure takes at least one string argument and returns a string. One procedure connects with another as a pipe.</dd> ++<dd><take> is a list whose elements are two exact integers; n and m, and the absolute values of n and m are N and M, respectively. First, the resulting string takes from the left n-characters, if it is non-negative, or all the characters but N-characters, if negative. Second, it takes from the right m-characters, if it is non-negative, or all the characters but M-characters, if negative. Then, it concatenates two set of characters taken. The second element can be omitted. If omitted, the default value is 0.</dd> ++<dd><converter> is a pair whose car value is a predicate procedure that checks whether <object> satisfies it, and cdr value is a procedure that takes the <object> as an argument and returns a string. When <object> satisfies the predicate procedure, all optional arguments are ineffective except <width>, <char>, <port>, and <string>.</dd> ++<dd><width> is an exact integer whose absolute value specifies the width of the resulting string. When the resulting string has fewer characters than the absolute value of <width>, it is placed rightmost with the rest being padded with <char>s, if <width> is positive, or it is placed leftmost with the rest being padded with <char>s, if <width> is negative. On the other hand, when the resulting string has more characters than the absolute value of <width>, the <width> is ignored. The default value is 0.</dd> + <dd><char> is a padding character. The default value is #\space.</dd> +-<dd><port> is an output port or a boolean. If an output port is +-specified, the resulting string and <string>s are output into +-that port and simultaneously returned as a string. If <port> is +-#t, the output port is current output port. If <port> is #f, the +-output is only returned as a string. The default value is #f.</dd> ++<dd><port> is an output port or a boolean. If an output port is specified, the resulting string and <string>s are output into that port and simultaneously returned as a string. If <port> is #t, the output port is current output port. If <port> is #f, the output is only returned as a string. The default value is #f.</dd> + <dd><string> is a string that is appended to the resulting string.</dd> + </dl> + +@@ -135,7 +118,7 @@ processes optional arguments in the following order; <exactness>, <radi + <precision>, <separator>, <sign> for the number type of <object>, or in the + following order; <writer>, <pipe>, <take> for all other types.</p> + +-<h2>Examples</h2> ++<h3>Examples</h3> + + <blockquote><pre><code>(cat 129.995 -10 2.) => "130.00 "</code></pre></blockquote> + <blockquote><pre><code>(cat 129.995 10 2.) => " 130.00"</code></pre></blockquote> +@@ -173,7 +156,8 @@ following order; <writer>, <pipe>, <take> for all other types. + <blockquote><pre><code>(cat 3 #t (cat 's) " " (cat "str" write)) => 3s "str""3s \"str\""</code></pre></blockquote> + <blockquote><pre><code>(cat 3 #t (cat 's #t) " " (cat "str" write)) => s3s "str""3s \"str\""</code></pre></blockquote> + <blockquote> +-<pre><code> ++<pre> ++<code> + (define-record-type :example + (make-example num str) + example? +@@ -215,15 +199,16 @@ ex => '#{:example} + </blockquote> + + +-<h1>Implementation</h1> ++<h2>Implementation</h2> + + <p> +-</p><p>The implementation below requires <a href="http://srfi.schemers.org/srfi-6/">SRFI 6</a> +-(Basic string ports) and <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> (Error ++The implementation below requires <a href="srfi-6.html">SRFI 6</a> ++(Basic string ports) and <a href="srfi-23.html">SRFI 23</a> (Error + reporting mechanism). + </p> + +-<pre><code> ++<pre> ++<code> + (define (cat object . rest) + (let* ((str-rest (part string? rest)) + (str-list (car str-rest)) +@@ -603,19 +588,19 @@ reporting mechanism). + </pre> + + +-<h1>Acknowledgment</h1> ++<h2>Acknowledgment</h2> + + + <p>I owe much to those who incite me to make this SRFI better. And I + must thank Michael Sperber for his encouragement and guidance during +-the draft period of <a href="http://srfi.schemers.org/srfi-51/">SRFI 51</a>, as the important part of this SRFI is ++the draft period of <a href="https://srfi.schemers.org/srfi-51/">SRFI 51</a>, as the important part of this SRFI is + based on SRFI 51. Without him, neither SRFI 51 nor SRFI 54 would have + been finilized. Again, I greatly appreciate his kindness and effort. + Finally, I deeply apologize to Francisco Solsona for bringing disgrace + upon him against my will early in the draft period.</p> + + +-<h1>Copyright</h1> ++<h2>Copyright</h2> + + <p>Copyright (C) Joo ChurlSoo (2004). All Rights Reserved.</p> + +@@ -642,11 +627,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> ++ <hr /> + <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + <!-- Created: Mon Feb 3 14:53:23 MET 2003 --> + <!-- hhmts start --> + Last modified: Sun Jan 28 13:40:19 MET 2007 + <!-- hhmts end --> +- +-</body></html> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-57.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-57.html +index e86c6be..a0e6db8 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-57.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-57.html +@@ -1,36 +1,51 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +-<HTML><HEAD><title>SRFI 57: Records</title> +-</HEAD> +-<BODY> +-<H1>Title</H1> +-Records +- +-<H1>Author</H1> +-André van Tonder +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see <A +-href="http://srfi.schemers.org/srfi-process.html">here</A>. You can access +-previous messages via <A +-href="http://srfi.schemers.org/srfi-57/mail-archive/maillist.html"> the +-archive of the mailing list</A>. +- +-<P> +-<UL> +- <LI>Received: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.1">2004/09/08</A></LI> +- <LI>Draft: 2004/09/08 - 2005/01/08</LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.2">2004/09/22</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.3">2004/11/08</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.6">2004/11/25</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.7">2004/12/08</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-57/srfi-57.html?rev=1.8">2005/03/07</A></LI> +- <LI>Final: 2005/03/07</LI> +-</UL> +- +-<H1>Abstract</H1> +- ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"><head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-57 ┃ ++┃ Commit: 9e2d77657e1366e3b87314d1a1a2071de0062e82 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--><title>SRFI 57: Records</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++</head> ++<body> ++<h1>SRFI 57: Records</h1> ++ ++<p>by André van Tonder</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 57 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-57/srfi-57.html">https://srfi.schemers.org/srfi-57/srfi-57.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+57%20%20+at+srfi+dotschemers+dot+org">srfi-57 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-57">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.1.html">2004-09-08</a></li> ++ <li>Draft: 2004-09-08--2005-01-08</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.2.html">2004-09-22</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.3.html">2004-11-08</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.6.html">2004-11-25</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.7.html">2004-12-08</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-57/srfi-57-1.8.html">2005-03-07</a></li> ++ <li>Final: 2005-03-07</li> ++</ul> ++ ++<h2>Abstract</h2> ++<p> + We describe a syntax for defining record types. + A predicate, constructor, + and field accessors and modifiers may be specified for each record +@@ -43,14 +58,14 @@ record type scheme. + A syntax is provided for constructing records by + field label, for in-place and for functional record + update, and for composing records. ++</p> + +- +-<H1>Rationale</H1> +- ++<h2>Rationale</h2> ++<p> + We extend the existing SRFI-9 [1] with the following features, + each listed with a brief justification. Expanded rationales appear + in the specification section below. +- ++</p> + <ul> + <li>A syntax for constructing record values by field label. Such a + feature is common in the prior art [2]. Indeed, the ability to +@@ -59,25 +74,29 @@ in the specification section below. + place. + Taking advantage of this feature can ease coding and increase readability and + robustness of code. +-</li><li> ++</li> ++<li> + A mechanism for defining and incrementally extending + polymorphic functions on families + of record types sharing a set of field labels. This automates + a common programming pattern which would otherwise be laborious to + code explicitly. +-</li><li>Facilities for record composition, functional record update, ++</li> ++<li>Facilities for record composition, functional record update, + including polymorphic + update, and linear in-place update. + These facilitate functional style programming with records. +-</li><li>A declaration syntax that allows shorter variations and ++</li> ++<li>A declaration syntax that allows shorter variations and + optional elements, to save labor and reduce namespace + pollution. +-</li></ul> ++</li> ++</ul> + + +-<H1>Specification</H1> ++<h2>Specification</h2> + +-<h2>Declaration</h2> ++<h3>Declaration</h3> + + <pre> <command or definition> + -> <record type definition> +@@ -131,12 +150,14 @@ in the specification section below. + + </pre> + +-<h3>Record types</h3> +- ++<h4>Record types</h4> ++<p> + An instance of <code>define-record-type</code> is equivalent to the following: +- ++</p> + <ul> +-<li> A list of field labels is associated with the record type <code><type name></code>, ++ <li> ++ <p> ++ A list of field labels is associated with the record type <code><type name></code>, + obtained by appending from left to right the lists of field labels + of any record + type schemes (see below) appearing in the <code><type clause></code>, +@@ -148,20 +169,28 @@ An instance of <code>define-record-type</code> is equivalent to the following: + to the semantics of <code>delete-duplicates</code> of SRFI-1. + Labels in the constructor clause must be + distinct. Labels in the field clauses must also be distinct. +- <p> +- +-</p></li><li>For each <code><scheme name></code> in <code><type clause></code>, the record type ++ </p> ++ </li> ++ <li> ++ <p> ++ For each <code><scheme name></code> in <code><type clause></code>, the record type + <code><type name></code> is said to be an <i>instance</i> of, or to + <i>conform</i> to the corresponding + record type scheme <code><scheme name></code> and to all + parent type schemes (see below) of <code><scheme name></code>. +- +-<p></p></li><li> <code><type name></code> is bound to a macro, described below, that can be used to construct record ++ </p> ++ </li> ++ <li> ++ <p> ++ <code><type name></code> is bound to a macro, described below, that can be used to construct record + values by label. It may also be registered, as specified in a + future SRFI, for performing pattern matching on record values of + type <code><type name></code>. +- <p> +-</p></li><li> If <code><constructor clause></code> is ++ </p> ++ </li> ++ <li> ++ <p> ++ If <code><constructor clause></code> is + of the form <code>(<constructor name> <field label> ...)</code>, then + <code><constructor name></code> is bound to a procedure that takes as many arguments as + there are <code><field label></code>s following it +@@ -172,9 +201,9 @@ An instance of <code>define-record-type</code> is equivalent to the following: + the procedure + <code><constructor name></code> takes as many arguments as there are field labels + associated with <code><type name></code>, in the default order defined above. +- <p></p><p> +- +- <code><constructor name></code> may be ++ </p> ++ <p> ++ <code><constructor name></code> may be + registered, in a way to be described in a future SRFI, for performing a + positional pattern match of the fields <code><field label> ...</code> + of record +@@ -182,42 +211,54 @@ An instance of <code>define-record-type</code> is equivalent to the following: + or of all fields + associated with <code><scheme name></code> in the default + order defined above in the second case. +- +-</p></li><li> <code><predicate name></code>, is bound to a predicate procedure ++ </p> ++ </li> ++ <li> ++ <p> ++ <code><predicate name></code>, is bound to a predicate procedure + that returns <code>#t</code> when given a record value that has been constructed using + the macro <code><type name></code> or the procedure <code><constructor name></code>, + and <code>#f</code> for any other + value. Values on which <code><predicate name></code>, if applied, would return + <code>#t</code>, are said to be <i>of type</i> <code><type name></code>. +- <p> +- +-</p></li><li> Field labels inherited from a <code><type scheme></code> or ++ </p> ++ </li> ++ <li> ++ <p> ++ Field labels inherited from a <code><type scheme></code> or + introduced in the <code><constructor clause></code> do not have to be + repeated in the + <code><field clause></code>s. + Where present, <code><field + clause></code>s may provide additional information on such fields, or may + declare additional fields. +- +- <p></p><p> ++ </p> ++ <p> + Field labels may be reused as the name of accessors or modifiers (a practice known + as punning). +- </p><p> +-</p><ul> +-<p></p><li> Each <code><accessor name></code> is bound to ++ </p> ++ </li> ++ <li> ++ <p> ++ Each <code><accessor name></code> is bound to + a procedure that takes a + value of type <code><type name></code>, + and returns the current value of the corresponding + field. It is an error to pass an accessor a value not of type + <code><type name></code>. +-<p></p></li><li> Each <code><modifier name></code> is bound to ++ </p> ++ </li> ++ <li> ++ <p> ++ Each <code><modifier name></code> is bound to + a procedure that takes a value of type <code><type name></code> + and a value which becomes the new value of the corresponding field. + It is an error to pass a modifier a first argument that is not of type + <code><type name></code>. + The return value of <code><modifier name></code> is unspecified. +- <p> +-</p></li></ul></li></ul> ++ </p> ++ </li> ++</ul> + + <p> + <code>Define-record-type</code> is generative: each use creates a new record type that is distinct +@@ -225,14 +266,16 @@ from all existing types, including + other record types and Scheme's predefined types. This SRFI only + specifies the behaviour of <code>define-record-type</code> at + top-level. +- +- +-</p><h3>Record type schemes</h3> ++</p> + ++<h4>Record type schemes</h4> ++<p> + An instance of <code>define-record-scheme</code> is equivalent to the following: +- ++</p> + <ul> +-<li> A list of field labels is associated with the type scheme <code><scheme name></code>, ++ <li> ++ <p> ++ A list of field labels is associated with the type scheme <code><scheme name></code>, + obtained by appending from left to right the lists of field labels + of any parent + type schemes appearing in the <code><scheme clause></code>, +@@ -243,9 +286,11 @@ An instance of <code>define-record-scheme</code> is equivalent to the following: + to the semantics of <code>delete-duplicates</code> of SRFI-1. + Labels in the constructor clause must be + distinct. Labels in the field clauses must also be distinct. +- <p> +- +-</p></li><li>A record type scheme is called a <i>parent scheme</i> of ++ </p> ++ </li> ++ <li> ++ <p> ++ A record type scheme is called a <i>parent scheme</i> of + <code><scheme name></code> if it appears in the + <code><scheme clause></code>, or if it is a parent scheme of + one of the <code><parent scheme name></code>'s appearing in the +@@ -254,16 +299,21 @@ An instance of <code>define-record-scheme</code> is equivalent to the following: + <code><scheme name></code> is said to + <i>extend</i> its parent type schemes. It is an error to extend a type scheme + that has not yet been defined. +- +- +-<p></p></li><li> <code><scheme name></code> may be bound to a macro or otherwise ++ </p> ++ </li> ++ <li> ++ <p> ++ <code><scheme name></code> may be bound to a macro or otherwise + registered, in a way to be + described in a future + SRFI, + for performing pattern matching on record + values conforming to <code><scheme name></code>. +- <p> +-</p></li><li>If <code><deconstructor clause></code> is ++ </p> ++ </li> ++ <li> ++ <p> ++ If <code><deconstructor clause></code> is + of the form <code>(<deconstructor name> <field label> ...)</code>, then + <code><deconstructor name></code> may be bound to a macro or otherwise + registered, in a way to be described in a future SRFI, for performing a +@@ -273,53 +323,58 @@ An instance of <code>define-record-scheme</code> is equivalent to the following: + If <code><deconstructor clause></code> is of the form <code><deconstructor name></code>, + the positional match will be on all fields + associated with <code><scheme name></code>, in the default order defined above. +- <p></p><p> +- +-</p></li><li> <code><predicate name></code>, is bound to a predicate procedure ++ </p> ++ </li> ++ <li> ++ <p> ++ <code><predicate name></code>, is bound to a predicate procedure + that returns <code>#t</code> when given a record value of any record type conforming + to <code><scheme name></code>, + and <code>#f</code> for any other +- value. +- <p> +- +-</p></li><li> Field labels inherited from a <code><parent type scheme></code> or ++ value. ++ </p> ++ </li> ++ <li> ++ <p> ++ Field labels inherited from a <code><parent type scheme></code> or + introduced in the <code><deconstructor clause></code> do not have to be + repeated in the + <code><field clause></code>s. + Where present, <code><field + clause></code>s may provide additional information on such fields, or may + declare additional fields. +- +- <p></p><p> +- Field labels may be reused as the name of accessors or modifiers (a practice known ++ </p> ++ <p> ++ Field labels may be reused as the name of accessors or modifiers (a practice known + as punning). +- </p><p> +-</p><ul> +-<p></p><li> Each <code><accessor name></code> is bound to ++ </p> ++ </li> ++ <li> ++ <p> ++ Each <code><accessor name></code> is bound to + a procedure that takes a + value conforming to <code><scheme name></code>, + and returns the current value of the corresponding + field. It is an error to pass an accessor a value not conforming to + <code><scheme name></code>. +-<p></p></li><li> Each <code><modifier name></code> is bound to ++ </p> ++ </li> ++ <li> ++ <p> ++ Each <code><modifier name></code> is bound to + a procedure that takes a value conforming to <code><scheme name></code> + and a value which becomes the new value of the corresponding field. + It is an error to pass a modifier a first argument that does not conform to + <code><scheme name></code>. + The return value of <code><modifier name></code> is unspecified. +- <p> +-</p></li></ul></li></ul> +- +- +- +- ++ </p> ++ </li> ++</ul> + + ++<h4>Examples</h4> + +- +-<p></p><h3>Examples</h3> +- +-<h4>A simple record:</h4> ++<h5>A simple record:</h5> + + <pre> (define-record-type point (make-point x y) point? + (x get-x set-x!) +@@ -333,10 +388,11 @@ An instance of <code>define-record-scheme</code> is equivalent to the following: + </pre> + + +-<h4>Record type schemes:</h4> +- ++<h5>Record type schemes:</h5> ++<p> + Let's declare a couple of record schemes. Record schemes do not have constructors. + They introduce polymorphic predicates and accessors. ++</p> + <pre> (define-record-scheme <point #f <point? + (x <point.x) + (y <point.y)) +@@ -344,11 +400,11 @@ They introduce polymorphic predicates and accessors. + (define-record-scheme <color #f <color? + (hue <color.hue)) + </pre> +- ++<p> + We now declare concrete instances of the above schemes. + Constructors may be introduced. + Predicates and accessors for concrete record types, when declared, are monomorphic. +- ++</p> + <pre> (define-record-type (point <point) make-point point? + (x point.x) + (y point.y)) +@@ -371,70 +427,70 @@ Predicates and accessors for concrete record types, when declared, are monomorph + (color-point.info cp) ==> <undefined> + </pre> + +-<h4>Optional elements:</h4> +- ++<h5>Optional elements:</h5> ++<p> + Elements may be left out if not desired, as the following examples illustrate: ++</p> + <pre> + (define-record-type node (make-node left right)) + (define-record-type leaf (make-leaf value)) + </pre> ++<p> + In these declarations, no predicates are bound. Also note that field labels listed in the + constructor do not have to be repeated in the field clause list unless + we want to bind getters or setters. +- ++</p> + <pre> + (define-record-type monday) + (define-record-type tuesday #f tuesday?) + </pre> ++<p> + Here <code>monday</code> has no declared constructor or predicate, while <code>tuesday</code> + has a predicate but no constructor. +- ++</p> + <pre> (define-record-type node make-node #f + (left left) + (right right)) + </pre> ++<p> + Here the constructor <code>make-node</code> has the default argument order and no predicate + is bound. Also note that field labels are + punned. +- +- +- +- +- +- +- ++</p> + +-<p></p><h4>A note on repeated fields and redefinitions</h4> + ++<h5>A note on repeated fields and redefinitions</h5> ++<p> + In the following example, two record type schemes define different accessors for the same field: +- ++</p> + <pre> (define-record-scheme foo #f #f (x foo-x)) + (define-record-scheme bar #f #f (x bar-x)) + (define-record-type (foo-bar foo bar)) + </pre> +- ++<p> + Since any value <code>fb</code> of type <code>foo-bar</code> conforms to both + <code>foo</code> and <code>bar</code>, both <code>foo-x</code> and <code>bar-x</code> + can be applied to <code>fb</code>, returning the value of the <code>x</code> field. +- ++</p> + <p> + In the following example, two declarations introduce + the same accessor: +- +-</p><pre> (define-record-scheme foo #f #f (x foo-x)) ++</p> ++<pre> (define-record-scheme foo #f #f (x foo-x)) + (define-record-type (bar foo) #f #f (x foo-x)) + </pre> ++<p> + As in any <code>define-...</code> form, later bindings replace earlier bindings. + After the second declaration is executed, + <code>foo-x</code> will be bound to the monomorphic accessor applicable only to values + of type <code>bar</code>, replacing its binding to the polymorphic accessor procedure + introduced in the <code>foo</code> declaration. +- ++</p> + + + +-<h2>Labeled record expressions</h2> +- ++<h3>Labeled record expressions</h3> ++<p> + The following syntax allows one to construct a record value by labels. The result + is a record value of type <code><type name></code> with each field + <code><field label></code> populated with the value of the corresponding +@@ -444,18 +500,17 @@ is a record value of type <code><type name></code> with each field + If this condition is not satisfied, an expansion time error must be signaled. The + runtime efficiency of a labeled record expression is required to be at least that of + the equivalent positional constructor. +- ++</p> + <pre> <expression> -> (<type name> (<field label> <expression>) ...) + </pre> +- +-</p><p> ++<p> + The order of evaluation of the expressions + <code><expression> ...</code> is undefined. ++</p> + + +- +-<h4>Rationale</h4> +- ++<h5>Rationale</h5> ++<p> + The traditional practice of instantiating record values with a positional constructor procedure + can lead to code that is hard to read and fragile under common operations such as + adding, removing, or rearranging field declarations. The ability to populate record values +@@ -464,8 +519,9 @@ more than two or three fields, or if it inherits fields from a type scheme. + Field labels are checked for validity + and the macro may be compiled to a positional constructor at expansion time, + thus eliminating a large class of potential programmer errors at no cost in efficiency. ++</p> + +-<h4>Example</h4> ++<h5>Example</h5> + + <pre> (color-point (info 'hi) + (x 1) +@@ -474,16 +530,16 @@ thus eliminating a large class of potential programmer errors at no cost in effi + ==> (color-point (hue <undefined>) (x 1) (y 2) (info hi)) + </pre> + +-<h2>Record update</h2> +- ++<h3>Record update</h3> ++<p> + The following syntax allows different forms of record update: +- ++</p> + <pre> <expression> -> (record-update <record> <scheme name> (<field label> <expression>) ...) + -> (record-update <record> <type name> (<field label> <expression>) ...) + -> (record-update! <record> <type name> (<field label> <expression>) ...) + -> (record-update! <record> <scheme name> (<field label> <expression>) ...) + </pre> +- ++<p> + The first alternative is used for polymorphic functional record update. The expression + <code><record></code> must evaluate to a record value that conforms to + <code><scheme name></code>. +@@ -492,8 +548,8 @@ the original <code><record></code>, with the given fields updated. The or + record value is unaffected. All the + <code><field label></code>s have to belong to the record type scheme <code><scheme name></code>. + If this condition is not satisfied, an expansion time error must be signaled. ++</p> + <p> +- + The second alternative is used for monomorphic functional record update. The expression + <code><record></code> must evaluate to a record value of type + <code><type name></code>. The result will be a new record value of type +@@ -501,8 +557,8 @@ The second alternative is used for monomorphic functional record update. The ex + record value is unaffected. All the + <code><field label></code>s have to belong to the record type <code><type name></code>. + If this condition is not satisfied, an expansion time error must be signaled. +-</p><p> +- ++</p> ++<p> + The third and fourth alternatives are used for linear, in-place record update. The expression + <code><record></code> must evaluate to a record value of type + <code><type name></code> or conforming to scheme <code><scheme name></code> . The result will be the original record value +@@ -511,21 +567,22 @@ mutated in place. + Note that a useful value is returned. All the + <code><field label></code>s have to belong to the record type <code><type name></code> or scheme <code><scheme name></code>. + If this condition is not satisfied, an expansion time error must be signaled. +- +-</p><p> ++</p> ++<p> + In these forms, the order of evaluation of the expressions + <code><expression> ...</code> is undefined. ++</p> + +-</p><h4>Rationale</h4> +- ++<h5>Rationale</h5> ++<p> + A mechanism for functional update facilitates and encourages functional-style programming + with records. + Note that polymorphic record update is not reducible + to the other operations we have listed and therefore has to be + provided as a built-in primitive [2]. +- +- +-<p></p><p>The linear version ++</p> ++<p> ++The linear version + <code>update!</code> is provided especially for cases where the programmer + knows that no other references to a value exist to produce what is, observationally, a + pure-functional result. In these cases, an <code>update</code> +@@ -533,33 +590,37 @@ operation may be replaced by <code>update!</code> for efficiency. + See SRFI-1 for a good discussion of the rationale behind linear update procedures. + Note, however, that in contrast with the linear procedures in SRFI-1, <code>update!</code> here is <i>required</i> + to mutate the original record. ++</p> + +-</p><h4>Examples</h4> +- ++<h5>Examples</h5> ++<p> + Monomorphic update: ++</p> + <pre> (define p (point (x 1) (y 2))) + + (record-update p point (x 7)) ==> (point (x 7) (y 2)) + p ==> (point (x 1) (y 2)) - original unaffected + </pre> +- ++<p> + Polymorphic update: ++</p> + <pre> (define cp (color-point (hue 'blue) (x 1) (y 2))) + + (record-update cp <point (x 7)) ==> (color-point (info <undefined>) (hue blue) (x 7) (y 2)) + cp ==> (color-point (info <undefined>) (hue blue) (x 1) (y 2)) + </pre> +- ++<p> + In-place update: ++</p> + <pre> (record-update! cp <point (x 7))) ==> (color-point (info <undefined>) (hue blue) (x 7) (y 2)) + cp ==> (color-point (info <undefined>) (hue blue) (x 7) (y 2)) + </pre> + + +-<h2>Record composition</h2> +- ++<h3>Record composition</h3> ++<p> + The following syntax provides a shorthand for composing record values: +- ++</p> + <pre> <expression> -> (record-compose (<import name> <record>) + ... + (<export-type name> (<field label> <expression>) ...)) +@@ -567,6 +628,7 @@ The following syntax provides a shorthand for composing record values: + <import name> -> <type name> + -> <scheme name> + </pre> ++<p> + Here each expression <code><record></code> must evaluate to a record value of type + <code><type name></code> or conforming to type scheme <code><scheme name></code>. The expression + evaluates to a new record value of type <code><export-type name></code> +@@ -582,36 +644,40 @@ any fields with the same labels already imported. Any remaining fields are und + All the + <code><field label></code>s have to belong to the record type <code><export type name></code>. + If this condition is not satisfied, an expansion time error must be signaled. +- ++</p> + <p> + The order of evaluation of the expressions <code><record> ...</code> and + <code><expression> ...</code> is undefined. All the + expressions <code><record> ...</code> will be evaluated, even + if their values might not be used in + the result. ++</p> + +-</p><h4>Rationale</h4> +- ++<h5>Rationale</h5> ++<p> + Calculi for composing record values, such as the above scheme, + may be used, for example, as units are used in +-PLT Scheme, or for writing what amounts to modules and functors in the sense of ML.<p> ++PLT Scheme, or for writing what amounts to modules and functors in the sense of ML. ++</p> ++<p> + Monomorphic record update is a special case of <code>record-compose</code>. The latter + may be used to express more general updates polymorphic in the + argument but monomorphic in the result type. +-</p><p> +- ++</p> + +-</p><h4>Examples</h4> + ++<h5>Examples</h5> ++<p> + Use <code>record-compose</code> for updates polymorphic in the argument but + monomorphic in the result type: ++</p> + <pre> (define cp (make-color-point 1 2 'green)) + + (record-compose (<point cp) (point (x 8))) ==> (point (x 8) (y 2)) + </pre> +- ++<p> + A more general composition example: +- ++</p> + <pre> (define cp (make-color-point 1 2 'green)) + (define c (make-color 'blue)) + +@@ -622,8 +688,9 @@ A more general composition example: + + ==> (color-point (info hi) (hue blue) (x 8) (y 2)) + </pre> +- ++<p> + Small module-functor example: ++</p> + <pre> + (define-record-type monoid #f #f + (mult monoid.mult) +@@ -662,50 +729,47 @@ Small module-functor example: + + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + + <p> + The reference implementation uses the macro mechanism of + R5RS. It assumes an existing implementation of SRFI-9, here denoted + srfi-9:define-record-type. It also contains a trivial use of + case-lambda from SRFI-16. +- +-</p><p> ++</p> ++<p> + The reference implementation, though relatively portable as a set of + <code>syntax-rules</code> macros, is slow. For practical + implementations, it is recommended that a procedural macro system be + used. Such implementations are provided separately in the discussion + archives. Unless otherwise stated by the author(s), they are covered + by the same copyright agreement as this document. +- +- +-</p><p> ++</p> ++<p> + This version depends on <code>define</code> being treated as a binding + form by <code>syntax-rules</code>. This is true for recent versions of portable syntax-case as used in Chez Scheme. It is + also true for PLT, for Scheme48, and possibly others. It also assumes + that the implementation of SRFI-9 binds the type name passed to it, which is a + hygienically introduced internal identifier, + using <code>define</code>. +- +- +-</p><p> ++</p> ++<p> + The SRFI specification was designed with the constraint that + all record expressions containing field labels be translatable into positional + expressions at macro-expansion time. For example, labeled record expressions + and patterns should be just as efficient as positional constructors and + patterns. This is true for the reference implementation. +- +-</p><p> ++</p> ++<p> + Only the names mentioned in the specification should be visible to + the user. Other + names should be hidden by a module system or naming convention. +-</p><p> +-The last section contains a few examples and (non-exhaustive) tests. +- +- +- + </p> +-<h2>Reference implementation </h2> ++<p> ++The last section contains a few examples and (non-exhaustive) tests. ++</p> ++ ++<h3>Reference implementation </h3> + + + <pre>;============================================================================================ +@@ -1178,7 +1242,7 @@ The last section contains a few examples and (non-exhaustive) tests. + + + +-<h2>Tests and examples</h2> ++<h3>Tests and examples</h3> + + <pre>;============================================================================================ + ; Examples: +@@ -1337,9 +1401,9 @@ The last section contains a few examples and (non-exhaustive) tests. + </pre> + + +-<h2>References</h2> ++<h3>References</h3> + +-<pre>[1] Richard Kelsey, Defining Record Types, SRFI-9: http://srfi.schemers.org/srfi-9/srfi-9.html ++<pre>[1] Richard Kelsey, Defining Record Types, SRFI-9: https://srfi.schemers.org/srfi-9/srfi-9.html + + [2] See e.g. + Benjamin C. Pierce, Types and Programming Languages, MIT Press 2002, and references therein. +@@ -1352,9 +1416,9 @@ The last section contains a few examples and (non-exhaustive) tests. + </pre> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + +-<p>Copyright (C) André van Tonder (2004). All Rights Reserved.</p> ++<p>Copyright (C) André van Tonder (2004). All Rights Reserved.</p> + + <p> + Permission is hereby granted, free of charge, to any person obtaining +@@ -1379,11 +1443,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +-<HR> ++<hr /> + +-<ADDRESS>Author: <A href="mailto:andre@het.brown.edu">André van +-Tonder</A></ADDRESS> +-<ADDRESS>Editor: <A href="mailto:srfi-editors@srfi.schemers.org">David Van Horn</A></ADDRESS> ++<address>Author: <a href="mailto:andre@het.brown.edu">André van ++Tonder</a></address> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> + <!-- Created: Tue Mar 16 19:01:34 EST 2004 --><!-- hhmts start --> +-Last modified: Wed Dec 8 15:31:34 EST 2004 +-<!-- hhmts end --></BODY></HTML> ++Last modified: Sun Jan 28 13:40:19 MET 2007 ++<!-- hhmts end --></body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-59.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-59.html +index 84b0680..118730a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-59.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-59.html +@@ -1,227 +1,240 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +-<HTML> +- <HEAD> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-59 ┃ ++┃ Commit: 38429b06d5ad7ff01ab613a7f2236fe4f3d03472 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 59: Vicinity</title> +- </HEAD> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> + +- <BODY> ++ <body> + +-<H1>Title</H1> ++<h1>SRFI 59: Vicinity</h1> + +-Vicinity ++<p>by Aubrey Jaffer</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 59 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-59/srfi-59.html">https://srfi.schemers.org/srfi-59/srfi-59.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Aubrey Jaffer +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see <A +-href="http://srfi.schemers.org/srfi-process.html">here</A>. You can access +-previous messages via <A +-href="http://srfi.schemers.org/srfi-59/mail-archive/maillist.html">the +-archive of the mailing list</A>. +- +-<P> +-<UL> +- <LI>Received: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-59/srfi-59.html?rev=1.1">2004/12/30</A></LI> +- <LI>Draft: 2004/12/30 - 2005/02/27</LI> +- <LI>Final: 2005/03/08</LI> +-</UL> +- +-<H1>Abstract</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+59%20%20+at+srfi+dotschemers+dot+org">srfi-59 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-59">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-59/srfi-59-1.1.html">2004-12-30</a></li> ++ <li>Draft: 2004-12-30--2005-02-27</li> ++ <li>Final: 2005-03-08</li> ++</ul> + ++<h2>Abstract</h2> ++<p> + A vicinity is a descriptor for a place in the file system. Vicinities + hide from the programmer the concepts of host, volume, directory, and + version. Vicinities express only the concept of a file environment + where a file name can be resolved to a file in a system independent + manner. +-<P> ++</p> ++<p> + All of these procedures are file-system dependent. Use of these + vicinity procedures can make programs file-system +-<EM>in</EM>dependent. +-<P> +- +-<H1>Rationale</H1> ++<em>in</em>dependent. ++</p> + ++<h2>Rationale</h2> ++<p> + Most computer languages expose the syntax of pathnames of the host + file-system when dealing with files. + But a great many programs require read access to data, text, or + library files they were installed with. +-<P> ++</p> ++<p> + Some programs use literal strings to locate accessory files, breaking + on installations with different destinations. + More savvy coders will construct pathnames from environment variables + or compile-time definitions. +-<P> ++</p> ++<p> + In most languages, programs intended for portability must condition + all manipulations of pathnames to the syntax and capabilities of the + host file-system. Inconsistent conditioning is a common cause of + porting failures. +-<P> ++</p> ++<p> + Common-Lisp attacks the general problem of naming files anywhere in +-any file system. It has a six-component <DFN>pathname</DFN> datatype ++any file system. It has a six-component <dfn>pathname</dfn> datatype + to represent names in the most complicated file-system imaginable; + names in simpler file systems use fewer components. +-<P> ++</p> ++<p> + In this arrangement, portable file-handling programs must be capable + of handling pathnames with 6 components, and those employing fewer. + But which component will be used is not obvious. Is a +-<CODE>".txt"</CODE> filename suffix a <I>type</I> or part of the +-<I>name</I>? +-<P> ++<code>".txt"</code> filename suffix a <i>type</i> or part of the ++<i>name</i>? ++</p> ++<p> + Vicinities attack a smaller problem, that of describing pathnames in 5 + predefined locations, and their sub-vicinities. Those predefined + locations cover the usual areas for ancillary and configuration files + used by Scheme implementations and programs. The +-<CODE>program-vicinity</CODE> is particularly useful as it is the ++<code>program-vicinity</code> is particularly useful as it is the + directory where the currently loading file is located. This is +-captured by redefining <CODE>load</CODE> to <CODE>fluid-let</CODE> a ++captured by redefining <code>load</code> to <code>fluid-let</code> a + top-level variable with its argument. +-<P> +-The <CODE>make-vicinity</CODE> and <CODE>pathname->vicinity</CODE> ++</p> ++<p> ++The <code>make-vicinity</code> and <code>pathname->vicinity</code> + procedures provide means to create new base vicinities. Base + vicinities should generally be absolute pathnames. +-<P> ++</p> ++<p> + Vicinities need not be tied to individual files in a file system. The + files named could be members of a zip archive, as Java does. +-Vicinities can even be used on <EM>flat</EM> file systems (which have ++Vicinities can even be used on <em>flat</em> file systems (which have + no directory structure) by having the vicinity express constraints on + the file name. On most systems a vicinity is a string. +-<P> +-<A HREF="http://swiss.csail.mit.edu/~jaffer/slib_2.html#SEC14"><TT>vicinity</TT></A> ++</p> ++<p> ++<a href="http://swiss.csail.mit.edu/~jaffer/slib_2.html#SEC14"><tt>vicinity</tt></a> + procedures are supported by all implementations in +-<A HREF="http://swiss.csail.mit.edu/~jaffer/SLIB">SLIB</A>. +-<P> ++<a href="http://swiss.csail.mit.edu/~jaffer/SLIB">SLIB</a>. ++</p> + +-<H1>Specification</H1> ++<h2>Specification</h2> + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="program-vicinity">program-vicinity</a></B> +-<DD><A NAME="IDX60"></A> ++<dl> ++<dt id="program-vicinity"><u>Function:</u> <b>program-vicinity</b> ++</dt><dd><a name="IDX60"></a> + Returns the vicinity of the currently loading Scheme code. For an + interpreter this would be the directory containing source code. For a + compiled system (with multiple files) this would be the directory + where the object or executable files are. If no file is currently +-loading, then the result is undefined. <STRONG>Warning:</STRONG> +-<CODE>program-vicinity</CODE> can return incorrect values if your program +-escapes back into a <CODE>load</CODE> continuation. +-</DL> ++loading, then the result is undefined. <strong>Warning:</strong> ++<code>program-vicinity</code> can return incorrect values if your program ++escapes back into a <code>load</code> continuation. ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="library-vicinity">library-vicinity</a></B> +-<DD><A NAME="IDX61"></A> ++<dl> ++<dt id="library-vicinity"><u>Function:</u> <b>library-vicinity</b> ++</dt><dd><a name="IDX61"></a> + Returns the vicinity of the shared Scheme library. +-</DL> ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="implementation-vicinity">implementation-vicinity</a></B> +-<DD><A NAME="IDX62"></A> ++<dl> ++<dt id="implementation-vicinity"><u>Function:</u> <b>implementation-vicinity</b> ++</dt><dd><a name="IDX62"></a> + Returns the vicinity of the underlying Scheme implementation. This + vicinity will likely contain startup code and messages and a compiler. +-</DL> ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="user-vicinity">user-vicinity</a></B> +-<DD><A NAME="IDX63"></A> ++<dl> ++<dt id="user-vicinity"><u>Function:</u> <b>user-vicinity</b> ++</dt><dd><a name="IDX63"></a> + Returns the vicinity of the current directory of the user. On most +-systems this is <TT>`""'</TT> (the empty string). +-</DL> ++systems this is <tt>`""'</tt> (the empty string). ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="home-vicinity">home-vicinity</a></B> +-<DD><A NAME="IDX64"></A> +-Returns the vicinity of the user's <EM>HOME</EM> directory, the directory +-<A NAME="IDX65"></A> ++<dl> ++<dt id="home-vicinity"><u>Function:</u> <b>home-vicinity</b> ++</dt><dd><a name="IDX64"></a> ++Returns the vicinity of the user's <em>HOME</em> directory, the directory ++<a name="IDX65"></a> + which typically contains files which customize a computer environment + for a user. If scheme is running without a user (eg. a daemon) or if +-this concept is meaningless for the platform, then <CODE>home-vicinity</CODE> +-returns <CODE>#f</CODE>. +-</DL> +- +- +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="in-vicinity">in-vicinity</a></B> <I>vicinity filename</I> +-<DD><A NAME="IDX67"></A> +-Returns a filename suitable for use by <CODE>load</CODE>, +-<CODE>open-input-file</CODE>, <CODE>open-output-file</CODE>, etc. The +-returned filename is <VAR>filename</VAR> in <VAR>vicinity</VAR>. +-<CODE>in-vicinity</CODE> should allow <VAR>filename</VAR> to override +-<VAR>vicinity</VAR> when <VAR>filename</VAR> is an absolute pathname +-and <VAR>vicinity</VAR> is equal to the value of +-<CODE>(user-vicinity)</CODE>. The behavior of +-<CODE>in-vicinity</CODE> when <VAR>filename</VAR> is absolute and +-<VAR>vicinity</VAR> is not equal to the value of +-<CODE>(user-vicinity)</CODE> is unspecified. For most systems +-<CODE>in-vicinity</CODE> can be <CODE>string-append</CODE>. </DL> +- +- +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="sub-vicinity">sub-vicinity</a></B> <I>vicinity name</I> +-<DD><A NAME="IDX68"></A> +-Returns the vicinity of <VAR>vicinity</VAR> restricted to <VAR>name</VAR>. This ++this concept is meaningless for the platform, then <code>home-vicinity</code> ++returns <code>#f</code>. ++</dd></dl> ++ ++ ++<dl> ++<dt id="in-vicinity"><u>Function:</u> <b>in-vicinity</b> <i>vicinity filename</i> ++</dt><dd><a name="IDX67"></a> ++Returns a filename suitable for use by <code>load</code>, ++<code>open-input-file</code>, <code>open-output-file</code>, etc. The ++returned filename is <var>filename</var> in <var>vicinity</var>. ++<code>in-vicinity</code> should allow <var>filename</var> to override ++<var>vicinity</var> when <var>filename</var> is an absolute pathname ++and <var>vicinity</var> is equal to the value of ++<code>(user-vicinity)</code>. The behavior of ++<code>in-vicinity</code> when <var>filename</var> is absolute and ++<var>vicinity</var> is not equal to the value of ++<code>(user-vicinity)</code> is unspecified. For most systems ++<code>in-vicinity</code> can be <code>string-append</code>. </dd></dl> ++ ++ ++<dl> ++<dt id="sub-vicinity"><u>Function:</u> <b>sub-vicinity</b> <i>vicinity name</i> ++</dt><dd><a name="IDX68"></a> ++Returns the vicinity of <var>vicinity</var> restricted to <var>name</var>. This + is used for large systems where names of files in subsystems could +-conflict. On systems with directory structure <CODE>sub-vicinity</CODE> will +-return a pathname of the subdirectory <VAR>name</VAR> of +-<VAR>vicinity</VAR>. +-</DL> ++conflict. On systems with directory structure <code>sub-vicinity</code> will ++return a pathname of the subdirectory <var>name</var> of ++<var>vicinity</var>. ++</dd></dl> + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="make-vicinity">make-vicinity</a></B> <I>dirpath</I> +-<DD><A NAME="IDX58"></A> +-Returns <VAR>dirpath</VAR> as a vicinity for use as first argument to +-<CODE>in-vicinity</CODE>. +-</DL> ++<dl> ++<dt id="make-vicinity"><u>Function:</u> <b>make-vicinity</b> <i>dirpath</i> ++</dt><dd><a name="IDX58"></a> ++Returns <var>dirpath</var> as a vicinity for use as first argument to ++<code>in-vicinity</code>. ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="pathname-to-vicinity">pathname->vicinity</a></B> <I>path</I> +-<DD><A NAME="IDX59"></A> +-Returns the vicinity containing <VAR>path</VAR>. ++<dl> ++<dt id="pathname-to-vicinity"><u>Function:</u> <b>pathname->vicinity</b> <i>path</i> ++</dt><dd><a name="IDX59"></a> ++Returns the vicinity containing <var>path</var>. + +-<PRE> +-(pathname->vicinity "/usr/local/lib/scm/Link.scm") +- => "/usr/local/lib/scm/" +-</PRE> ++<pre> ++(pathname->vicinity "/usr/local/lib/scm/Link.scm") ++ => "/usr/local/lib/scm/" ++</pre> + +-</DL> ++</dd></dl> + + +-<P> +-<DL> +-<DT><U>Function:</U> <B><a name="vicinity:suffix-p">vicinity:suffix?</a></B> <I>chr</I> +-<DD><A NAME="IDX66"></A> +-Returns the <SAMP>`#t'</SAMP> if <VAR>chr</VAR> is a vicinity suffix character; and +-<CODE>#f</CODE> otherwise. Typical vicinity suffixes are <SAMP>`/'</SAMP>, +-<SAMP>`:'</SAMP>, and <SAMP>`\'</SAMP>, +-</DL> ++<dl> ++<dt id="vicinity:suffix-p"><u>Function:</u> <b>vicinity:suffix?</b> <i>chr</i> ++</dt><dd><a name="IDX66"></a> ++Returns the <samp>`#t'</samp> if <var>chr</var> is a vicinity suffix character; and ++<code>#f</code> otherwise. Typical vicinity suffixes are <samp>`/'</samp>, ++<samp>`:'</samp>, and <samp>`\'</samp>, ++</dd></dl> + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + ++<p> + This code is taken from +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/Template.scm</A> ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/Template.scm</a> + and +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/require.scm</A> +-<P> ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/require.scm</a> ++</p> + +-<PRE> ++<pre> + ;;@ (implementation-vicinity) should be defined to be the pathname of +-;;; the directory where any auxiliary files to your Scheme ++;;; the directory where any auxillary files to your Scheme + ;;; implementation reside. + (define (implementation-vicinity) + (case (software-type) +@@ -310,10 +323,9 @@ and + (string-append vic name *vicinity-suffix*)))))) + ;@ + (define (make-vicinity pathname) pathname) +-</PRE> +-<P> ++</pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Aubrey Jaffer (2004). All Rights Reserved.</p> + + <p> +@@ -340,11 +352,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <HR> +- <ADDRESS>Editor: <A HREF="mailto:srfi-editors@srfi.schemers.org">David Van Horn</A></ADDRESS> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Thu Dec 30 23:48:06 EST 2004 ++Last modified: Sun Jan 28 13:40:18 MET 2007 + <!-- hhmts end --> +- </BODY> +-</HTML> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-6.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-6.html +index 890e205..58e9d7b 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-6.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-6.html +@@ -1,116 +1,156 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-6 ┃ ++┃ Commit: 578cc762141f5a8a062c55a511cb76d6c7407f65 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 6: Basic String Ports</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 6: Basic String Ports</h1> + +-SRFI-6: Basic String Ports ++<p>by William D Clinger</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 6 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-6/srfi-6.html">https://srfi.schemers.org/srfi-6/srfi-6.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> +- +-William D Clinger +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-6/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/04/07 +-<LI>Draft: 1999/04/26-1999/06/24 +-<LI>Final: 1999/07/01 +-</UL> ++<h2>Status</h2> + ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+6+at+srfi+dotschemers+dot+org">srfi-6@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-6">archive</a>.</p> ++<ul> ++ <li>Received: 1999-04-07</li> ++ <li>Draft: 1999-04-26--1999-06-24</li> ++ <li>Final: 1999-07-01</li> ++</ul> + +-<H1>Abstract</H1> + ++<h2>Abstract</h2> ++<p> + Scheme's i/o primitives are extended by adding three new procedures +-that ++that: ++</p> + <ul> +-<li>create an input port from a string, +-<li>create an output port whose contents are accumulated in Scheme's +- working memory instead of an external file, and +-<li>extract the accumulated contents of an in-memory output port +- and return them in the form of a string. ++ <li> ++ create an input port from a string; ++ </li> ++ <li> ++ create an output port whose contents are accumulated in Scheme's ++ working memory instead of an external file; and ++ </li> ++ <li> ++ extract the accumulated contents of an in-memory output port and ++ return them in the form of a string. ++ </li> + </ul> + +-<H1>Issues</H1> +- ++<h2>Issues</h2> ++<p> + None. ++</p> + +-<H1>Rationale</H1> +- ++<h2>Rationale</h2> ++<p> + Scheme's procedures for performing input and output from and to ports + become more useful when extended by string ports. The interface + described here has been in use since 1986 or before, and is currently + supported by several of the major implementations. ++</p> + +-<H1>Specification</H1> +- ++<h2>Specification</h2> ++<p> + This specification is taken from the MacScheme Reference Manual. +- ++</p> + <dl> +-<dt><a name="open-input-string"></a><pre> ++<dt id="open-input-string"><pre> + (OPEN-INPUT-STRING string) ;procedure +-</pre><dd> ++</pre> ++</dt> ++<dd> ++<p> + Takes a string and returns an input port that delivers characters + from the string. The port can be closed by + <code>CLOSE-INPUT-PORT</code>, though its storage will be + reclaimed by the garbage collector if it becomes inaccessible. ++</p> + <pre> + (define p +- (open-input-string "(a . (b . c . ())) 34")) ++ (open-input-string "(a . (b . (c . ()))) 34")) + +- (input-port? p) --> #t +- (read p) --> (a b c) +- (read p) --> 34 +- (eof-object? (peek-char p)) --> #t ++ (input-port? p) --> #t ++ (read p) --> (a b c) ++ (read p) --> 34 ++ (eof-object? (peek-char p)) --> #t + </pre> +- +-<dt><a name="open-output-string"></a><pre> ++</dd> ++<dt id="open-output-string"><pre> + (OPEN-OUTPUT-STRING) ;procedure +-</pre><dd> ++</pre> ++</dt> ++<dd> ++<p> + Returns an output port that will accumulate characters for + retrieval by <code>GET-OUTPUT-STRING</code>. The port can be + closed by the procedure <code>CLOSE-OUTPUT-PORT</code>, though + its storage will be reclaimed by the garbage collector if it + becomes inaccessible. ++</p> + <pre> + (let ((q (open-output-string)) + (x '(a b c))) + (write (car x) q) + (write (cdr x) q) +- (get-output-string q)) --> "a(b c)" ++ (get-output-string q)) --> "a(b c)" + </pre> +- +-<dt><a name="get-output-string"></a><pre> ++</dd> ++<dt id="get-output-string"><pre> + (GET-OUTPUT-STRING output-port) ;procedure +-</pre><dd> ++</pre> ++</dt> ++<dd> ++<p> + Given an output port created by <code>OPEN-OUTPUT-STRING</code>, + returns a string consisting of the characters that have been + output to the port so far. ++</p> ++</dd> + </dl> + + +-<H1>Implementation</H1> +- ++<h2>Implementation</h2> ++<p> + What follows is just an outline of how these procedures might be + implemented, because a real implementation would also have to + redefine <code>READ</code>, <code>WRITE</code>, and so forth + to use <code>PEEK-CHAR</code>, <code>READ-CHAR</code>, and + <code>WRITE-CHAR</code> as redefined below. +- ++</p> + <p> + Since the code for <code>READ</code> and <code>WRITE</code> + would be identical to code that already exists in any + implementation, however, it should not be necessary for this + SRFI to include that code within this SRFI. Including it + would only detract from the readability of this implementation. +- +-<p> ++</p> + <pre> + ; This implementation is not IEEE- or R5RS-compliant, + ; for the following reasons: +@@ -244,7 +284,7 @@ would only detract from the readability of this implementation. + (set! open-output-string make-output-string) + (set! get-output-string + (lambda (x) +- (list->string (reverse (output-string:contents x))))) ++ (list->string (reverse (output-string:contents x))))) + + (set! input-port? + (lambda (x) +@@ -278,7 +318,7 @@ would only detract from the readability of this implementation. + (i (input-string:next x)) + (n (input-string:size x))) + (if (input-string:open? x) +- (if (< i n) ++ (if (< i n) + (string-ref s i) + eof) + (error))) +@@ -294,7 +334,7 @@ would only detract from the readability of this implementation. + (i (input-string:next x)) + (n (input-string:size x))) + (if (input-string:open? x) +- (if (< i n) ++ (if (< i n) + (let ((c (string-ref s i))) + (input-string:next! x (+ i 1)) + c) +@@ -318,8 +358,10 @@ would only detract from the readability of this implementation. + (if #f #f))) + </pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> ++<p> + Copyright (C) William D Clinger (1999). All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -343,11 +385,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Mon Feb 24 11:54:01 MET 2003 ++Last modified: Fri Aug 7 09:46:28 MST 2009 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-60.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-60.html +index 09e098a..c6a30e8 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-60.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-60.html +@@ -1,81 +1,96 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +-<HTML> +- <HEAD> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-60 ┃ ++┃ Commit: ed47121122a6146b720f107b989c48db0df5f6c4 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 60: Integers as Bits</title> +- </HEAD> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> + +- <BODY> ++ <body> + +-<H1>Title</H1> ++<h1>SRFI 60: Integers as Bits</h1> + +-SRFI 60: Integers as Bits ++<p>by Aubrey Jaffer</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 60 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-60/srfi-60.html">https://srfi.schemers.org/srfi-60/srfi-60.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Aubrey Jaffer ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+60%20%20+at+srfi+dotschemers+dot+org">srfi-60 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-60">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-60/srfi-60-1.1.html">2005-01-03</a></li> ++ <li>Draft: 2005-01-03--2005-03-03</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-60/srfi-60-1.2.html">2005-01-10</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-60/srfi-60-1.4.html">2005-01-27</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-60/srfi-60-1.5.html">2005-01-29</a></li> ++ <li>Final: 2005-03-08</li> ++</ul> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see <A +-href="http://srfi.schemers.org/srfi-process.html">here</A>. You can access +-previous messages via <A +-href="http://srfi.schemers.org/srfi-60/mail-archive/maillist.html">the +-archive of the mailing list</A>. +- +-<P> +-<UL> +- <LI>Received: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-60/srfi-60.html?rev=1.1">2005/01/03</A></LI> +- <LI>Draft: 2005/01/03 - 2005/03/03</LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-60/srfi-60.html?rev=1.2">2005/01/10</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-60/srfi-60.html?rev=1.4">2005/01/27</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-60/srfi-60.html?rev=1.5">2005/01/29</A></LI> +- <LI>Final: 2005/03/08</LI> +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + Treating integers as two's-complement strings of bits is an arcane but + important domain of computer science. It is used for: + +-<UL> +-<LI>hashing; ++<ul> ++<li>hashing; + +-<LI>Galois-field[2] calculations of error-detecting and ++</li><li>Galois-field[2] calculations of error-detecting and + error-correcting codes; + +-<LI>cryptography and ciphers; ++</li><li>cryptography and ciphers; + +-<LI>pseudo-random number generation; ++</li><li>pseudo-random number generation; + +-<LI>register-transfer-level modeling of digital logic designs; ++</li><li>register-transfer-level modeling of digital logic designs; + +-<LI>Fast-Fourier transforms; ++</li><li>Fast-Fourier transforms; + +-<LI>packing and unpacking numbers in persistent data structures; ++</li><li>packing and unpacking numbers in persistant data structures; + +-<LI>space-filling curves with applications to dimension reduction and ++</li><li>space-filling curves with applications to dimension reduction and + sparse multi-dimensional database indexes; and + +-<LI>generating approximate seed values for root-finders and ++</li><li>generating approximate seed values for root-finders and + transcendental function algorithms. + +-</UL> +-<P> ++</li></ul> + +-<H1>Rationale</H1> + ++<h2>Rationale</h2> ++<p> + This proposal describes the +-<A HREF="http://swiss.csail.mit.edu/~jaffer/SLIB">SLIB</A> module +-<A HREF="http://swiss.csail.mit.edu/~jaffer/slib_5.html#SEC88"><TT>logical</TT></A>, ++<a href="http://swiss.csail.mit.edu/~jaffer/SLIB">SLIB</a> module ++<a href="http://swiss.csail.mit.edu/~jaffer/slib_5.html#SEC88"><tt>logical</tt></a>, + which has been used for those purposes listed above. +-<P> ++</p> ++<p> + The discussions of the withdrawn +-<A HREF="http://srfi.schemers.org/srfi-33/">SRFI-33: "Integer +-Bitwise-operation Library"</A> seemed to founder on consistency of ++<a href="https://srfi.schemers.org/srfi-33/">SRFI-33: "Integer ++Bitwise-operation Library"</a> seemed to founder on consistency of + procedure names and arity; and on perceived competition with the + boolean arrays of SRFI-47. +-<P> ++</p> ++<p> + I have implemented both logical number operations and boolean arrays; + and have not been conflicted as to their application. I used boolean + arrays to construct very fast indexes for database tables having +@@ -83,530 +98,591 @@ millions of records. To avoid running out of RAM, creation of megabit + arrays should be explicit; so the boolean array procedures put their + results into a passed array. In contrast, these procedures are purely + functional. +-<P> ++</p> + +-<H3>Bits and Complements</H3> ++<h3>Bits and Complements</h3> + ++<p> + A bit-index in these descriptions is nonnegative with the least + significant bit at index 0. + A positive integer has a finite number of "1" bits. + A negative integer has a finite number of "0" bits. +-<P> ++</p> ++<p> + The reference implementation is written using only Scheme integer + operations. Thus the only exposure of the underlying representation + is the ranges of fixnums. +-<P> +-The <DFN>complement</DFN> describes the representation of negative ++</p> ++<p> ++The <dfn>complement</dfn> describes the representation of negative + integers. With one's-complement fixnums, the range of integers is +--(2<SUP><I>n</I></SUP>) to 2<SUP><I>n</I></SUP>, and there are two ++-(2<sup><i>n</i></sup>) to 2<sup><i>n</i></sup>, and there are two + possible representations of 0. With two's-complement fixnums, the +-range of integers is -(2<SUP><I>n</I></SUP>+1) to +-2<SUP><I>n</I></SUP>. +-<P> ++range of integers is -(2<sup><i>n</i></sup>+1) to ++2<sup><i>n</i></sup>. ++</p> ++<p> + Since we treat integers as having two's-complement negations, + the two's-complement of an integer is simply its negation. + The one's-complement of an integer is computed by lognot: +- +-<PRE> ++</p> ++<pre> + (define (lognot n) (- -1 n)) +-</PRE> +-<P> ++</pre> + +-<H3>Bitwise Operations and Integer Properties</H3> ++<h3>Bitwise Operations and Integer Properties</h3> + +-The <TT>logior</TT>, <TT>logxor</TT>, <TT>logand</TT>, +-<TT>lognot</TT>, <TT>logtest</TT>, <TT>logbit?</TT> (logbitp), +-<TT>ash</TT>, <TT>logcount</TT>, and <TT>integer-length</TT> +-procedures are from Common-Lisp. <TT>Logior</TT>, <TT>logxor</TT>, +-and <TT>logand</TT> have been extended to accept any arity. +-Opportunities to use an <I>n</I>-ary version of <TT>logtest</TT> have ++<p> ++The <tt>logior</tt>, <tt>logxor</tt>, <tt>logand</tt>, ++<tt>lognot</tt>, <tt>logtest</tt>, <tt>logbit?</tt> (logbitp), ++<tt>ash</tt>, <tt>logcount</tt>, and <tt>integer-length</tt> ++procedures are from Common-Lisp. <tt>Logior</tt>, <tt>logxor</tt>, ++and <tt>logand</tt> have been extended to accept any arity. ++Opportunities to use an <i>n</i>-ary version of <tt>logtest</tt> have + not been frequent enough to justify its extension. +-<P> +-In the <DFN>Bitwise Operations</DFN>, rather than striving for ++</p> ++<p> ++In the <dfn>Bitwise Operations</dfn>, rather than striving for + orthogonal completeness, I have concentrated on a nearly minimal set + of bitwise logical functions sufficient to support the uses listed + above. +-<P> +-Although any two of <TT>logior</TT>, <TT>logxor</TT>, and +-<TT>logand</TT> (in combination with <TT>lognot</TT>) are sufficient ++</p> ++<p> ++Although any two of <tt>logior</tt>, <tt>logxor</tt>, and ++<tt>logand</tt> (in combination with <tt>lognot</tt>) are sufficient + to generate all the two-input logic functions, having these three + means that any nontrivial two-input logical function can be + synthesized using just one of these two-input primaries with zero or +-one calls to <TT>lognot</TT>. +-<P> +-<TT>bitwise-if</TT> is what SRFI-33 calls <TT>bitwise-merge</TT>. +-<P> +-The SRFI-33 aliases: <TT>bitwise-ior</TT>, <TT>bitwise-xor</TT>, +-<TT>bitwise-and</TT>, <TT>bitwise-not</TT>, <TT>bitwise-merge</TT>, +-<TT>any-bits-set?</TT>, and <TT>bit-count</TT> are also provided. +-<P> +-<TT>log2-binary-factors</TT> (alias <TT>first-set-bit</TT>) is a ++one calls to <tt>lognot</tt>. ++</p> ++<p> ++<tt>bitwise-if</tt> is what SRFI-33 calls <tt>bitwise-merge</tt>. ++</p> ++<p> ++The SRFI-33 aliases: <tt>bitwise-ior</tt>, <tt>bitwise-xor</tt>, ++<tt>bitwise-and</tt>, <tt>bitwise-not</tt>, <tt>bitwise-merge</tt>, ++<tt>any-bits-set?</tt>, and <tt>bit-count</tt> are also provided. ++</p> ++<p> ++<tt>log2-binary-factors</tt> (alias <tt>first-set-bit</tt>) is a + useful function which is simple but non-obvious: +- +-<PRE> ++</p> ++<pre> + (define (log2-binary-factors n) + (+ -1 (integer-length (logand n (- n))))) +-</PRE> ++</pre> + +-<H3>Bit Within Word and Field of Bits</H3> ++<h3>Bit Within Word and Field of Bits</h3> + +-The <DFN>Bit Within Word</DFN> and <DFN>Field of Bits</DFN> procedures ++<p> ++The <dfn>Bit Within Word</dfn> and <dfn>Field of Bits</dfn> procedures + are used for modeling digital logic and accessing binary data + structures in software. +-<P> +-I have changed to <TT>copy-bit-field</TT> argument order to be +-consistent with the other <DFN>Field of Bits</DFN> procedures: the +-<VAR>start</VAR> and <VAR>end</VAR> index arguments are last. +-This makes them analogous to the argument order to <TT>substring</TT> +-and SRFI-47 arrays, which took their cue from <TT>substring</TT>. +-<P> +-These <VAR>start</VAR> and <VAR>end</VAR> index arguments are not +-compatible with SRFI-33's <VAR>size</VAR> and <VAR>position</VAR> +-arguments (occurring first) in its <TT>bit-field</TT> procedures. +-Both define <TT>copy-bit-field</TT>; the arguments and purposes being ++</p> ++<p> ++I have changed to <tt>copy-bit-field</tt> argument order to be ++consistent with the other <dfn>Field of Bits</dfn> procedures: the ++<var>start</var> and <var>end</var> index arguments are last. ++This makes them analogous to the argument order to <tt>substring</tt> ++and SRFI-47 arrays, which took their cue from <tt>substring</tt>. ++</p> ++<p> ++These <var>start</var> and <var>end</var> index arguments are not ++compatible with SRFI-33's <var>size</var> and <var>position</var> ++arguments (occurring first) in its <tt>bit-field</tt> procedures. ++Both define <tt>copy-bit-field</tt>; the arguments and purposes being + incompatible. +-<P> +-A procedure in slib/logical.scm, <TT>logical:rotate</TT>, rotated a ++</p> ++<p> ++A procedure in slib/logical.scm, <tt>logical:rotate</tt>, rotated a + given number of low-order bits by a given number of bits. This + function was quite servicable, but I could not name it adequately. I +-have replaced it with <TT>rotate-bit-field</TT> with the addition of a +-<VAR>start</VAR> argument. This new function rotates a given field +-(from positions <VAR>start</VAR> to <VAR>end</VAR>) within an integer; ++have replaced it with <tt>rotate-bit-field</tt> with the addition of a ++<var>start</var> argument. This new function rotates a given field ++(from positions <var>start</var> to <var>end</var>) within an integer; + leaving the rest unchanged. +-<P> +-Another problematic name was <TT>logical:ones</TT>, which generated an +-integer with the least significant <VAR>k</VAR> bits set. Calls to +-<TT>bit-field</TT> could have replaced its uses . But the definition ++</p> ++<p> ++Another problematic name was <tt>logical:ones</tt>, which generated an ++integer with the least significant <var>k</var> bits set. Calls to ++<tt>bit-field</tt> could have replaced its uses . But the definition + was so short that I just replaced its uses with: +- +-<PRE> +-(lognot (ash -1 <VAR>k</VAR>)) +-</PRE> +-<P> +-The <TT>bit-reverse</TT> procedure was then the only one which took a +-<VAR>width</VAR> argument. So I replaced it with +-<TT>reverse-bit-field</TT>. +-<P> +-The <DFN>Lamination</DFN> and <DFN>Gray-code</DFN> functions were ++</p> ++<pre> ++(lognot (ash -1 <var>k</var>)) ++</pre> ++<p> ++The <tt>bit-reverse</tt> procedure was then the only one which took a ++<var>width</var> argument. So I replaced it with ++<tt>reverse-bit-field</tt>. ++</p> ++<p> ++The <dfn>Lamination</dfn> and <dfn>Gray-code</dfn> functions were + moved to +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/phil-spc.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/phil-spc.scm</A> +-<P> ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/phil-spc.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/phil-spc.scm</a> ++</p> + +-<H3>Bits as Booleans</H3> ++<h3>Bits as Booleans</h3> + +-<DFN>Bits as Booleans</DFN> provides the procedures to convert between ++<p> ++<dfn>Bits as Booleans</dfn> provides the procedures to convert between + integers and lists of booleans. There is no comparable facility in + SRFI-33. +-<P> ++</p> + + +-<H1>Specification</H1> ++<h2>Specification</h2> + + + +-<H3><A NAME="SEC97">Bitwise Operations</A></H3> ++<h3 id="SEC97">Bitwise Operations</h3> + +-<P> +-<DL> +-<DT><U>Function:</U> <B>logand</B> <I>n1 ...</I> +-<DD><A NAME="IDX487"></A> +-<DT><U>Function:</U> <B>bitwise-and</B> <I>n1 ...</I> +-<DD><A NAME="IDX488"></A> ++<dl> ++<dt><u>Function:</u> <b>logand</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX487"> ++</dd> ++<dt><u>Function:</u> <b>bitwise-and</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX488"> ++<p> + Returns the integer which is the bit-wise AND of the integer + arguments. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (logand #b1100 #b1010) 2) +- => "1000" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>logior</B> <I>n1 ...</I> +-<DD><A NAME="IDX489"></A> +-<DT><U>Function:</U> <B>bitwise-ior</B> <I>n1 ...</I> +-<DD><A NAME="IDX490"></A> ++</p> ++<pre> ++(number->string (logand #b1100 #b1010) 2) ++ => "1000" ++</pre> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>logior</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX489"> ++</dd> ++<dt><u>Function:</u> <b>bitwise-ior</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX490"> ++<p> + Returns the integer which is the bit-wise OR of the integer arguments. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (logior #b1100 #b1010) 2) +- => "1110" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>logxor</B> <I>n1 ...</I> +-<DD><A NAME="IDX491"></A> +-<DT><U>Function:</U> <B>bitwise-xor</B> <I>n1 ...</I> +-<DD><A NAME="IDX492"></A> ++</p> ++<pre> ++(number->string (logior #b1100 #b1010) 2) ++ => "1110" ++</pre> ++</dd> ++</dl> ++ ++ ++ ++<dl> ++<dt><u>Function:</u> <b>logxor</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX491"> ++</dd> ++<dt><u>Function:</u> <b>bitwise-xor</b> <i>n1 ...</i> ++</dt> ++<dd id="IDX492"> ++<p> + Returns the integer which is the bit-wise XOR of the integer + arguments. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (logxor #b1100 #b1010) 2) +- => "110" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>lognot</B> <I>n</I> +-<DD><A NAME="IDX493"></A> +-<DT><U>Function:</U> <B>bitwise-not</B> <I>n</I> +-<DD><A NAME="IDX494"></A> ++</p> ++<pre> ++(number->string (logxor #b1100 #b1010) 2) ++ => "110" ++</pre> ++</dd> ++</dl> ++ ++ ++ ++<dl> ++<dt><u>Function:</u> <b>lognot</b> <i>n</i> ++</dt> ++<dd id="IDX493"> ++</dd> ++<dt><u>Function:</u> <b>bitwise-not</b> <i>n</i> ++</dt> ++<dd id="IDX494"> ++<p> + Returns the integer which is the one's-complement of the integer argument. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (lognot #b10000000) 2) +- => "-10000001" +-(number->string (lognot #b0) 2) +- => "-1" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>bitwise-if</B> <I>mask n0 n1</I> +-<DD><A NAME="IDX495"></A> +-<DT><U>Function:</U> <B>bitwise-merge</B> <I>mask n0 n1</I> +-<DD><A NAME="IDX496"></A> +-Returns an integer composed of some bits from integer <VAR>n0</VAR> and some +-from integer <VAR>n1</VAR>. A bit of the result is taken from <VAR>n0</VAR> if the +-corresponding bit of integer <VAR>mask</VAR> is 1 and from <VAR>n1</VAR> if that bit +-of <VAR>mask</VAR> is 0. +-</DL> +- +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>logtest</B> <I>j k</I> +-<DD><A NAME="IDX497"></A> +-<DT><U>Function:</U> <B>any-bits-set?</B> <I>j k</I> +-<DD><A NAME="IDX498"></A> +- +-<PRE> ++</p> ++<pre> ++(number->string (lognot #b10000000) 2) ++ => "-10000001" ++(number->string (lognot #b0) 2) ++ => "-1" ++</pre> ++</dd> ++</dl> ++ ++ ++ ++<dl> ++<dt><u>Function:</u> <b>bitwise-if</b> <i>mask n0 n1</i> ++</dt> ++<dd id="IDX495"> ++</dd> ++<dt><u>Function:</u> <b>bitwise-merge</b> <i>mask n0 n1</i> ++</dt> ++<dd id="IDX496"> ++<p> ++Returns an integer composed of some bits from integer <var>n0</var> and some ++from integer <var>n1</var>. A bit of the result is taken from <var>n0</var> if the ++corresponding bit of integer <var>mask</var> is 1 and from <var>n1</var> if that bit ++of <var>mask</var> is 0. ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>logtest</b> <i>j k</i> ++</dt> ++<dd id="IDX497"> ++</dd> ++<dt><u>Function:</u> <b>any-bits-set?</b> <i>j k</i> ++</dt> ++<dd id="IDX498"> ++<pre> + (logtest j k) == (not (zero? (logand j k))) + +-(logtest #b0100 #b1011) => #f +-(logtest #b0100 #b0111) => #t +-</PRE> ++(logtest #b0100 #b1011) => #f ++(logtest #b0100 #b0111) => #t ++</pre> ++</dd> ++</dl> + +-</DL> + + ++<h3 id="SEC98">Integer Properties</h3> + +-<H3><A NAME="SEC98">Integer Properties</A></H3> + +-<P> +-<DL> +-<DT><U>Function:</U> <B>logcount</B> <I>n</I> +-<DD><A NAME="IDX499"></A> +-<DT><U>Function:</U> <B>bit-count</B> <I>n</I> +-<DD><A NAME="IDX500"></A> +-Returns the number of bits in integer <VAR>n</VAR>. If integer is positive, ++<dl> ++<dt><u>Function:</u> <b>logcount</b> <i>n</i> ++</dt> ++<dd id="IDX499"> ++</dd> ++<dt><u>Function:</u> <b>bit-count</b> <i>n</i> ++</dt> ++<dd id="IDX500"> ++<p> ++Returns the number of bits in integer <var>n</var>. If integer is positive, + the 1-bits in its binary representation are counted. If negative, the + 0-bits in its two's-complement binary representation are counted. If 0, + 0 is returned. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> ++</p> ++<pre> + (logcount #b10101010) +- => 4 ++ => 4 + (logcount 0) +- => 0 ++ => 0 + (logcount -2) +- => 1 +-</PRE> ++ => 1 ++</pre> ++</dd> ++</dl> + +-</DL> + +-<P> +-<DL> +-<DT><U>Function:</U> <B>integer-length</B> <I>n</I> +-<DD><A NAME="IDX501"></A> +-Returns the number of bits necessary to represent <VAR>n</VAR>. + + +-<P> ++<dl> ++<dt><u>Function:</u> <b>integer-length</b> <i>n</i> ++</dt> ++<dd id="IDX501"> ++<p> ++Returns the number of bits neccessary to represent <var>n</var>. ++</p> ++<p> + Example: +- +-<PRE> ++</p> ++<pre> + (integer-length #b10101010) +- => 8 ++ => 8 + (integer-length 0) +- => 0 ++ => 0 + (integer-length #b1111) +- => 4 +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>log2-binary-factors</B> <I>n</I> +-<DD><A NAME="IDX502"></A> +-<DT><U>Function:</U> <B>first-set-bit</B> <I>n</I> +-<DD><A NAME="IDX503"></A> +-Returns the number of factors of two of integer <VAR>n</VAR>. This value +-is also the bit-index of the least-significant <SAMP>`1'</SAMP> bit in +-<VAR>n</VAR>. ++ => 4 ++</pre> ++</dd> ++</dl> + + + +-<PRE> ++<dl> ++<dt><u>Function:</u> <b>log2-binary-factors</b> <i>n</i> ++</dt> ++<dd id="IDX502"> ++</dd> ++<dt><u>Function:</u> <b>first-set-bit</b> <i>n</i> ++</dt> ++<dd id="IDX503"> ++<p> ++Returns the number of factors of two of integer <var>n</var>. This value ++is also the bit-index of the least-significant <samp>`1'</samp> bit in ++<var>n</var>. ++</p> ++<pre> + (require 'printf) + (do ((idx 0 (+ 1 idx))) +- ((> idx 16)) +- (printf "%s(%3d) ==> %-5d %s(%2d) ==> %-5d\n" ++ ((> idx 16)) ++ (printf "%s(%3d) ==> %-5d %s(%2d) ==> %-5d\n" + 'log2-binary-factors + (- idx) (log2-binary-factors (- idx)) + 'log2-binary-factors + idx (log2-binary-factors idx))) + -| +-log2-binary-factors( 0) ==> -1 log2-binary-factors( 0) ==> -1 +-log2-binary-factors( -1) ==> 0 log2-binary-factors( 1) ==> 0 +-log2-binary-factors( -2) ==> 1 log2-binary-factors( 2) ==> 1 +-log2-binary-factors( -3) ==> 0 log2-binary-factors( 3) ==> 0 +-log2-binary-factors( -4) ==> 2 log2-binary-factors( 4) ==> 2 +-log2-binary-factors( -5) ==> 0 log2-binary-factors( 5) ==> 0 +-log2-binary-factors( -6) ==> 1 log2-binary-factors( 6) ==> 1 +-log2-binary-factors( -7) ==> 0 log2-binary-factors( 7) ==> 0 +-log2-binary-factors( -8) ==> 3 log2-binary-factors( 8) ==> 3 +-log2-binary-factors( -9) ==> 0 log2-binary-factors( 9) ==> 0 +-log2-binary-factors(-10) ==> 1 log2-binary-factors(10) ==> 1 +-log2-binary-factors(-11) ==> 0 log2-binary-factors(11) ==> 0 +-log2-binary-factors(-12) ==> 2 log2-binary-factors(12) ==> 2 +-log2-binary-factors(-13) ==> 0 log2-binary-factors(13) ==> 0 +-log2-binary-factors(-14) ==> 1 log2-binary-factors(14) ==> 1 +-log2-binary-factors(-15) ==> 0 log2-binary-factors(15) ==> 0 +-log2-binary-factors(-16) ==> 4 log2-binary-factors(16) ==> 4 +-</PRE> +- +-</DL> +- +- +- +-<H3><A NAME="SEC99">Bit Within Word</A></H3> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>logbit?</B> <I>index n</I> +-<DD><A NAME="IDX504"></A> +-<DT><U>Function:</U> <B>bit-set?</B> <I>index n</I> +-<DD><A NAME="IDX505"></A> +- +-<PRE> ++log2-binary-factors( 0) ==> -1 log2-binary-factors( 0) ==> -1 ++log2-binary-factors( -1) ==> 0 log2-binary-factors( 1) ==> 0 ++log2-binary-factors( -2) ==> 1 log2-binary-factors( 2) ==> 1 ++log2-binary-factors( -3) ==> 0 log2-binary-factors( 3) ==> 0 ++log2-binary-factors( -4) ==> 2 log2-binary-factors( 4) ==> 2 ++log2-binary-factors( -5) ==> 0 log2-binary-factors( 5) ==> 0 ++log2-binary-factors( -6) ==> 1 log2-binary-factors( 6) ==> 1 ++log2-binary-factors( -7) ==> 0 log2-binary-factors( 7) ==> 0 ++log2-binary-factors( -8) ==> 3 log2-binary-factors( 8) ==> 3 ++log2-binary-factors( -9) ==> 0 log2-binary-factors( 9) ==> 0 ++log2-binary-factors(-10) ==> 1 log2-binary-factors(10) ==> 1 ++log2-binary-factors(-11) ==> 0 log2-binary-factors(11) ==> 0 ++log2-binary-factors(-12) ==> 2 log2-binary-factors(12) ==> 2 ++log2-binary-factors(-13) ==> 0 log2-binary-factors(13) ==> 0 ++log2-binary-factors(-14) ==> 1 log2-binary-factors(14) ==> 1 ++log2-binary-factors(-15) ==> 0 log2-binary-factors(15) ==> 0 ++log2-binary-factors(-16) ==> 4 log2-binary-factors(16) ==> 4 ++</pre> ++</dd> ++</dl> ++ ++ ++ ++<h3 id="SEC99">Bit Within Word</h3> ++ ++<dl> ++<dt><u>Function:</u> <b>logbit?</b> <i>index n</i> ++</dt> ++<dd id="IDX504"> ++</dd> ++<dt><u>Function:</u> <b>bit-set?</b> <i>index n</i> ++</dt> ++<dd id="IDX505"> ++<pre> + (logbit? index n) == (logtest (expt 2 index) n) + +-(logbit? 0 #b1101) => #t +-(logbit? 1 #b1101) => #f +-(logbit? 2 #b1101) => #t +-(logbit? 3 #b1101) => #t +-(logbit? 4 #b1101) => #f +-</PRE> ++(logbit? 0 #b1101) => #t ++(logbit? 1 #b1101) => #f ++(logbit? 2 #b1101) => #t ++(logbit? 3 #b1101) => #t ++(logbit? 4 #b1101) => #f ++</pre> ++</dd> ++</dl> + +-</DL> + +-<P> +-<DL> +-<DT><U>Function:</U> <B>copy-bit</B> <I>index from bit</I> +-<DD><A NAME="IDX506"></A> +-Returns an integer the same as <VAR>from</VAR> except in the <VAR>index</VAR>th bit, +-which is 1 if <VAR>bit</VAR> is <CODE>#t</CODE> and 0 if <VAR>bit</VAR> is <CODE>#f</CODE>. +- +- +-<P> ++<dl> ++<dt><u>Function:</u> <b>copy-bit</b> <i>index from bit</i> ++</dt> ++<dd id="IDX506"> ++<p> ++Returns an integer the same as <var>from</var> except in the <var>index</var>th bit, ++which is 1 if <var>bit</var> is <code>#t</code> and 0 if <var>bit</var> is <code>#f</code>. ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (copy-bit 0 0 #t) 2) => "1" +-(number->string (copy-bit 2 0 #t) 2) => "100" +-(number->string (copy-bit 2 #b1111 #f) 2) => "1011" +-</PRE> +- +-</DL> ++</p> ++<pre> ++(number->string (copy-bit 0 0 #t) 2) => "1" ++(number->string (copy-bit 2 0 #t) 2) => "100" ++(number->string (copy-bit 2 #b1111 #f) 2) => "1011" ++</pre> ++</dd> ++</dl> + + + +-<H3><A NAME="SEC100">Field of Bits</A></H3> ++<h3 id="SEC100">Field of Bits</h3> + +-<P> +-<DL> +-<DT><U>Function:</U> <B>bit-field</B> <I>n start end</I> +-<DD><A NAME="IDX507"></A> +-Returns the integer composed of the <VAR>start</VAR> (inclusive) through +-<VAR>end</VAR> (exclusive) bits of <VAR>n</VAR>. The <VAR>start</VAR>th bit becomes ++<dl> ++<dt><u>Function:</u> <b>bit-field</b> <i>n start end</i> ++</dt> ++<dd id="IDX507"> ++<p> ++Returns the integer composed of the <var>start</var> (inclusive) through ++<var>end</var> (exclusive) bits of <var>n</var>. The <var>start</var>th bit becomes + the 0-th bit in the result. +- +- +-<P> ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (bit-field #b1101101010 0 4) 2) +- => "1010" +-(number->string (bit-field #b1101101010 4 9) 2) +- => "10110" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>copy-bit-field</B> <I>to from start end</I> +-<DD><A NAME="IDX508"></A> +-Returns an integer the same as <VAR>to</VAR> except possibly in the +-<VAR>start</VAR> (inclusive) through <VAR>end</VAR> (exclusive) bits, which are +-the same as those of <VAR>from</VAR>. The 0-th bit of <VAR>from</VAR> becomes the +-<VAR>start</VAR>th bit of the result. +- +- +-<P> ++</p> ++<pre> ++(number->string (bit-field #b1101101010 0 4) 2) ++ => "1010" ++(number->string (bit-field #b1101101010 4 9) 2) ++ => "10110" ++</pre> ++</dd> ++</dl> ++ ++<dl> ++<dt><u>Function:</u> <b>copy-bit-field</b> <i>to from start end</i> ++</dt> ++<dd id="IDX508"> ++<p> ++Returns an integer the same as <var>to</var> except possibly in the ++<var>start</var> (inclusive) through <var>end</var> (exclusive) bits, which are ++the same as those of <var>from</var>. The 0-th bit of <var>from</var> becomes the ++<var>start</var>th bit of the result. ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (copy-bit-field #b1101101010 0 0 4) 2) +- => "1101100000" +-(number->string (copy-bit-field #b1101101010 -1 0 4) 2) +- => "1101101111" +-(number->string (copy-bit-field #b110100100010000 -1 5 9) 2) +- => "110100111110000" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>ash</B> <I>n count</I> +-<DD><A NAME="IDX509"></A> +-<DT><U>Function:</U> <B>arithmetic-shift</B> <I>n count</I> +-<DD><A NAME="IDX510"></A> ++</p> ++<pre> ++(number->string (copy-bit-field #b1101101010 0 0 4) 2) ++ => "1101100000" ++(number->string (copy-bit-field #b1101101010 -1 0 4) 2) ++ => "1101101111" ++(number->string (copy-bit-field #b110100100010000 -1 5 9) 2) ++ => "110100111110000" ++</pre> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>ash</b> <i>n count</i> ++</dt> ++<dd id="IDX509"> ++</dd> ++<dt><u>Function:</u> <b>arithmetic-shift</b> <i>n count</i> ++</dt> ++<dd id="IDX510"> ++<p> + Returns an integer equivalent to +-<CODE>(inexact->exact (floor (* <VAR>n</VAR> (expt 2 <VAR>count</VAR>))))</CODE>. +- +- +-<P> ++<code>(inexact->exact (floor (* <var>n</var> (expt 2 <var>count</var>))))</code>. ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (ash #b1 3) 2) +- => "1000" +-(number->string (ash #b1010 -1) 2) +- => "101" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>rotate-bit-field</B> <I>n count start end</I> +-<DD><A NAME="IDX511"></A> +-Returns <VAR>n</VAR> with the bit-field from <VAR>start</VAR> to <VAR>end</VAR> +-cyclically permuted by <VAR>count</VAR> bits towards high-order. +- +- +-<P> ++</p> ++<pre> ++(number->string (ash #b1 3) 2) ++ => "1000" ++(number->string (ash #b1010 -1) 2) ++ => "101" ++</pre> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>rotate-bit-field</b> <i>n count start end</i> ++</dt> ++<dd id="IDX511"> ++<p> ++Returns <var>n</var> with the bit-field from <var>start</var> to <var>end</var> ++cyclically permuted by <var>count</var> bits towards high-order. ++</p> ++<p> + Example: +- +-<PRE> +-(number->string (rotate-bit-field #b0100 3 0 4) 2) +- => "10" +-(number->string (rotate-bit-field #b0100 -1 0 4) 2) +- => "10" +-(number->string (rotate-bit-field #b110100100010000 -1 5 9) 2) +- => "110100010010000" +-(number->string (rotate-bit-field #b110100100010000 1 5 9) 2) +- => "110100000110000" +-</PRE> +- +-</DL> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>reverse-bit-field</B> <I>n start end</I> +-<DD><A NAME="IDX512"></A> +-Returns <VAR>n</VAR> with the order of bits <VAR>start</VAR> to <VAR>end</VAR> ++</p> ++<pre> ++(number->string (rotate-bit-field #b0100 3 0 4) 2) ++ => "10" ++(number->string (rotate-bit-field #b0100 -1 0 4) 2) ++ => "10" ++(number->string (rotate-bit-field #b110100100010000 -1 5 9) 2) ++ => "110100010010000" ++(number->string (rotate-bit-field #b110100100010000 1 5 9) 2) ++ => "110100000110000" ++</pre> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>reverse-bit-field</b> <i>n start end</i> ++</dt> ++<dd id="IDX512"> ++<p> ++Returns <var>n</var> with the order of bits <var>start</var> to <var>end</var> + reversed. ++</p> ++<pre> ++(number->string (reverse-bit-field #xa7 0 8) 16) ++ => "e5" ++</pre> ++</dd> ++</dl> + + + +-<PRE> +-(number->string (reverse-bit-field #xa7 0 8) 16) +- => "e5" +-</PRE> +- +-</DL> +- +- +- +-<H3><A NAME="SEC101">Bits as Booleans</A></H3> +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>integer->list</B> <I>k len</I> +-<DD><A NAME="IDX513"></A> +-<DT><U>Function:</U> <B>integer->list</B> <I>k</I> +-<DD><A NAME="IDX514"></A> +-<CODE>integer->list</CODE> returns a list of <VAR>len</VAR> booleans corresponding +-to each bit of the given integer. #t is coded for each 1; #f for 0. +-The <VAR>len</VAR> argument defaults to <CODE>(integer-length <VAR>k</VAR>)</CODE>. ++<h3 id="SEC101">Bits as Booleans</h3> + + +-<P> +-<DT><U>Function:</U> <B>list->integer</B> <I>list</I> +-<DD><A NAME="IDX515"></A> +-<CODE>list->integer</CODE> returns an integer formed from the booleans in the +-list <VAR>list</VAR>, which must be a list of booleans. A 1 bit is coded for ++<dl> ++<dt><u>Function:</u> <b>integer->list</b> <i>k len</i> ++</dt> ++<dd id="IDX513"> ++</dd> ++<dt><u>Function:</u> <b>integer->list</b> <i>k</i> ++</dt> ++<dd id="IDX514"> ++<p> ++<code>integer->list</code> returns a list of <var>len</var> booleans corresponding ++to each bit of the non-negative integer <var>k</var>. #t is coded for each 1; #f for 0. ++The <var>len</var> argument defaults to <code>(integer-length <var>k</var>)</code>. ++</p> ++</dd> ++<dt><u>Function:</u> <b>list->integer</b> <i>list</i> ++</dt> ++<dd id="IDX515"> ++<p> ++<code>list->integer</code> returns an integer formed from the booleans in the ++list <var>list</var>, which must be a list of booleans. A 1 bit is coded for + each #t; a 0 bit for #f. ++</p> ++<p> ++<code>integer->list</code> and <code>list->integer</code> are inverses so far as ++<code>equal?</code> is concerned. ++</p> ++</dd> ++</dl> + +- +-<P> +-<CODE>integer->list</CODE> and <CODE>list->integer</CODE> are inverses so far as +-<CODE>equal?</CODE> is concerned. +-</DL> +- +- +-<P> +-<DL> +-<DT><U>Function:</U> <B>booleans->integer</B> <I>bool1 ...</I> +-<DD><A NAME="IDX516"></A> +-Returns the integer coded by the <VAR>bool1</VAR> ... arguments. +-</DL> ++<dl> ++<dt><u>Function:</u> <b>booleans->integer</b> <i>bool1 ...</i> ++</dt> ++<dd id="IDX516"> ++<p> ++Returns the integer coded by the <var>bool1</var> ... arguments. ++</p> ++</dd> ++</dl> + + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/logical.scm</A> ++<p> ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/logical.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/logical.scm</a> + implements the integers-as-bits procedures for R4RS or R5RS compliant + Scheme implementations. +-<P> +-<PRE> ++</p> ++<pre> + ;;;; "logical.scm", bit access and operations for integers for Scheme + ;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer + ; +@@ -844,10 +920,10 @@ Scheme implementations. + ;;(define (logical:rotate k count len) (rotate-bit-field k count 0 len)) + ;;(define (logical:ones deg) (lognot (ash -1 deg))) + ;;(define integer-expt expt) ; legacy name +-</PRE> ++</pre> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) Aubrey Jaffer (2004, 2005). All Rights Reserved.</p> + + <p> +@@ -874,11 +950,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <HR> +- <ADDRESS>Editor: <A HREF="mailto:srfi-editors@srfi.schemers.org">David Van Horn</A></ADDRESS> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Sat Jan 29 13:16:05 EST 2005 ++Last modified: Thu Jan 12 08:16:58 MET 2012 + <!-- hhmts end --> +- </BODY> +-</HTML> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-61.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-61.html +index db64d63..6dcecc5 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-61.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-61.html +@@ -1,41 +1,59 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-61 ┃ ++┃ Commit: ae4977ee14783f133bd1dee7b33a75ffdc388dbd ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 61: A more general COND clause</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + + +-<H1>Title</H1> ++<h1>SRFI 61: A more general <code>cond</code> clause</h1> + +-<p>A more general <code>cond</code> clause</p> + ++<p>by Taylor Campbell</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 61 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-61/srfi-61.html">https://srfi.schemers.org/srfi-61/srfi-61.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> + +-<p>Taylor Campbell</p> ++<h2>Status</h2> + +- +-<H1>Status</H1> +-<p>This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access previous messages via +-<a href="http://srfi.schemers.org/srfi-61/mail-archive/maillist.html">the archive of the mailing list</a>.</p> +-<ul> <li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-61/srfi-61.txt?rev=1.1">2005/01/04</a></li> +- <li>Draft: 2005/01/03-2005/03/04</li> +- <li>Final: 2005/07/21</li> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+61+at+srfi+dotschemers+dot+org">srfi-61@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-61">archive</a>.</p> ++<ul> <li>Received: <a href="https://srfi.schemers.org/srfi-61/srfi-61-1.1.txt">2005-01-04</a></li> ++ <li>Draft: 2005-01-03--2005-03-04</li> ++ <li>Final: 2005-07-21</li> + </ul> + + +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + <p>This SRFI proposes an extension to the <code>cond</code> syntax to allow a more + general clause, one that allows binding the results of tests as in the + <code>=></code> clauses and user-defined meaning of the success & failure of tests.</p> + + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p>The present set of <code>cond</code> clauses is based on simple boolean testing. It + is prohibitively inexpressive in that the condition part of a <code>cond</code> +@@ -49,7 +67,7 @@ be assigned on a per-clause basis, and it also allows the condition to + return multiple values to be passed to the receiver.</p> + + +-<H1>Specification</H1> ++<h2>Specification</h2> + + <p>The <code><cond clause></code> production in the formal syntax of Scheme as written + by R5RS in section 7.1.3 is extended with a new option:</p> +@@ -71,7 +89,7 @@ returns a false value, however, the clause is abandoned and the next + one is tried.</p> + + +-<H1>Examples</H1> ++<h2>Examples</h2> + + <p>This <code>port->char-list</code> procedure accepts an input port and returns a list + of all the characters it produces until the end.</p> +@@ -102,7 +120,7 @@ type of <code>cond</code> clause:</p> + </blockquote> + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + + <p>The entirety of a syntax transformer for the new <code>cond</code> syntax is given + here. It uses an auxiliary macro, <code>cond/maybe-more</code>, to simplify the +@@ -155,7 +173,7 @@ code is in the public domain.</p> + </blockquote> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + + <p>Copyright (C) 2004 Taylor Campbell. All rights reserved.</p> + +@@ -183,8 +201,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-62.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-62.html +index 304071e..c8f5bbb 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-62.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-62.html +@@ -1,38 +1,63 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html><head><title>SRFI 62: S-expression comments</title></head><body> +- +-<h1>Title</h1> +- +-S-expression comments +- +-<h1>Author</h1> +- +-Taylor Campbell +- +-<h1>Status</h1> +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-You can access previous messages via <a href="http://srfi.schemers.org/srfi-62/mail-archive/maillist.html">the archive of the mailing list</a>. +-<p></p><ul> +- +-<li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-62/srfi-62.txt?rev=1.1">2005/01/04</a> +-</li><li>Draft: 2005/01/03-2005/03/04 +-</li><li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-62/srfi-62.txt?rev=1.3">2005/02/27</a> +-</li><li>Final: 2005/07/21</li> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-62 ┃ ++┃ Commit: 33b08322b6db1bd50d2657d7b7145590f0637276 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 62: S-expression comments</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> ++ ++ <body> ++ ++<h1>SRFI 62: S-expression comments</h1> ++ ++<p>by Taylor Campbell</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 62 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-62/srfi-62.html">https://srfi.schemers.org/srfi-62/srfi-62.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+62+at+srfi+dotschemers+dot+org">srfi-62@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-62">archive</a>.</p> ++<ul> ++ ++<li>Received: <a href="https://srfi.schemers.org/srfi-62/srfi-62-1.1.txt">2005-01-04</a> ++</li><li>Draft: 2005-01-03--2005-03-04 ++</li><li>Revised: <a href="https://srfi.schemers.org/srfi-62/srfi-62-1.3.txt">2005-02-27</a> ++</li><li>Final: 2005-07-21</li> + </ul> + +-<h1>Abstract</h1> ++<h2>Abstract</h2> + + <p> + This SRFI proposes a simple extension to Scheme's lexical syntax that + allows individual S-expressions to be made into comments, ignored by +-the reader. This contrasts with the standard Lisp semicolon commnets, ++the reader. This contrasts with the standard Lisp semicolon comments, + which make the reader ignore the remainder of the line, and the +-slightly less common block comments, as <a href="http://srfi.schemers.org/srfi-30/srfi-30.html">SRFI 30</a> ++slightly less common block comments, as <a href="srfi-30.html">SRFI 30</a> + defines: both of these mechanisms comment out slices of text, not + S-expressions. + </p> + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + + <p> + Line and block comments are useful for embedding textual commentary in +@@ -43,16 +68,15 @@ subsequently removing the comments and re-introducing the S-expressions + themselves. + </p> + +-<h1>Informal specification</h1> ++<h2>Informal specification</h2> + + <p> + A new octothorpe reader syntax character is defined, <tt>#\;</tt>, such + that the reader ignores the S-expression following the <tt>#;</tt> and + proceeds on to the S-expression after that. For example, +-<br> + </p> + <table border="0" cellpadding="0" cellspacing="10"> +- <tbody><tr> ++ <tr> + <td><tt>(+ 1 #;(* 2 3) 4)</tt></td> + <td>-reads-> <tt>(+ 1 4)</tt></td> + <td>-evals-> <tt>5</tt></td> +@@ -72,7 +96,7 @@ proceeds on to the S-expression after that. For example, + <td>-reads-> <tt>(abs -16)</tt></td> + <td>-evals-> <tt>16</tt></td> + </tr> +-</tbody></table> ++</table> + + <p> + Some examples of nested S-expression comments may appear confusing at +@@ -92,17 +116,16 @@ leaving only <tt>'d</tt>. + <p> + That is a fairly special case of nested S-expression comments. Others + are somewhat simpler for intuition to grasp immediately, such as: +-<br> +-<br> ++</p> ++<p> + <tt>(list 'a #;(list 'b #;c 'd) 'e)</tt> -reads-> <tt>(list (quote a) (quote e))</tt> -evals-> <tt>(a e)</tt> +-<br> +-<br> ++</p> ++<p> + There are also some other somewhat peculiar examples, such as in dotted + lists and at the end of lists, which are still simple to grasp: +-<br> +-<br> ++</p> + <table border="0" cellpadding="0" cellspacing="10"> +- <tbody><tr> ++ <tr> + <td><tt>'(a . #;b c)</tt></td> + <td>-reads-> <tt>(quote (a . c))</tt></td> + </tr> +@@ -110,8 +133,7 @@ lists and at the end of lists, which are still simple to grasp: + <td><tt>'(a . b #;c)</tt></td> + <td>-reads-> <tt>(quote (a . b))</tt></td> + </tr> +-</tbody></table> +-</p> ++</table> + + <p> + Note, however, that any text that is invalid without S-expression +@@ -120,9 +142,8 @@ prefix, <tt>#;</tt>, must be followed by a complete S-expression (and + after that either a complete S-expression or a special token such as a + closing parenthesis, a dot in dotted lists, or the end of file); for + instance, the following are all errors: +-<br> +-<br> +-</p><ul> ++</p> ++<ul> + <li><tt>(#;a . b)</tt></li> + <li><tt>(a . #;b)</tt></li> + <li><tt>(a #;. b)</tt></li> +@@ -130,36 +151,42 @@ instance, the following are all errors: + <li><tt>(#; #;x #;y . z)</tt></li> + <li><tt>(#; #;x . z)</tt></li> + </ul> +-<p></p> + +-<h1>Formal specification</h1> ++<h2>Formal specification</h2> + + <p> + R5RS's formal syntax is modified as follows: +-</p><ul> ++</p> ++<ul> + <li>In section 7.1.1, a <tt>#;</tt> option is added to the + <tt><token></tt> non-terminal.</li> + <li>In section 7.1.2, a non-terminal <tt><commented datum></tt> + is defined: +-<pre> <commented datum> ---> "#;" <datum> <datum> ++<pre> ++ <commented datum> ---> "#;" <datum> <datum> + </pre></li> + <li>Also in section 7.1.2, the <tt><datum></tt> non-terminal is + modified to have a <tt><commented datum></tt> option.</li> + <li>Finally in section 7.1.2, the <tt><list></tt> and + <tt><vector></tt> non-terminals are replaced with the + following rules, along with two auxiliary ones: +-<pre> <list> ---> "(" <datum>* <optional dot> <delimiter prefix> ")" ++<pre> ++ <list> ---> "(" <datum>* <optional dot> <delimiter prefix> ")" + <vector> ---> "#(" <datum>* <delimiter prefix> ")" + <optional dot> ---> <empty> | <datum> <delimiter prefix> "." <datum> + <delimiter prefix> ---> <empty> | "#;" <datum> <delimiter prefix> + </pre></li> + </ul> ++<p> + The first datum in a <tt><commented datum></tt> is ignored + semantically, as is any datum immediately following a <tt>#;</tt> token + in a delimiter prefix. +-<br><br> ++</p> ++<p> + All of the new or modified rules are presented here: +-<pre> 7.1.1: ++</p> ++<pre> ++ 7.1.1: + + <token> ---> <identifier> | <boolean> | <number> + | <character> | <string> +@@ -175,9 +202,8 @@ All of the new or modified rules are presented here: + <optional dot> ---> <empty> | <datum> <delimiter prefix> "." <datum> + <delimiter prefix> ---> <empty> | "#;" <datum> <delimiter prefix> + </pre> +-<p></p> + +-<h1>Copyright</h1> ++<h2>Copyright</h2> + + <p>Copyright (C) 2004 Taylor Campbell. All rights reserved.</p> + +@@ -205,7 +231,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + + +- <hr> ++ <hr /> + <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> +- +-</body></html> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-63.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-63.html +index d846e0f..93abab6 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-63.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-63.html +@@ -1,134 +1,159 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +-<HTML> +- <HEAD> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-63 ┃ ++┃ Commit: 797846151be7dbec2a79da600e9a80ac71bf0914 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 63: Homogeneous and Heterogeneous Arrays</title> +- </HEAD> +- +- <BODY> +- +-<H1>Title</H1> +- +-Homogeneous and Heterogeneous Arrays +- +-<H1>Author</H1> +- +-Aubrey Jaffer +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see <A +-HREF="http://srfi.schemers.org/srfi-process.html">here</A>. You can +-access previous messages via <A +-HREF="http://srfi.schemers.org/srfi-63/mail-archive/maillist.html">the +-archive of the mailing list</A>. +-<P> +-</P><UL> +- <LI>Received: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-63/srfi-63.html?rev=1.3">2005/01/17</A></LI> +- <LI>Draft: 2005/01/17 - 2005/03/18</LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-63/srfi-63.html?rev=1.4">2005/01/27</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-63/srfi-63.html?rev=1.5">2005/01/29</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-63/srfi-63.html?rev=1.6">2005/04/08</A></LI> +- <LI>Revised: <A HREF="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-63/srfi-63.html?rev=1.7">2005/04/27</A></LI> +- <LI>Final: 2005/04/27</LI> +-</UL> +- +-<H1>Abstract</H1> +- ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> ++ ++ <body> ++ ++<h1>SRFI 63: Homogeneous and Heterogeneous Arrays</h1> ++ ++<p>by Aubrey Jaffer</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 63 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-63/srfi-63.html">https://srfi.schemers.org/srfi-63/srfi-63.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+63+at+srfi+dotschemers+dot+org">srfi-63@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-63">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-63/srfi-63-1.3.html">2005-01-17</a></li> ++ <li>Draft: 2005-01-17--2005-03-18</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-63/srfi-63-1.4.html">2005-01-27</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-63/srfi-63-1.5.html">2005-01-29</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-63/srfi-63-1.6.html">2005-04-08</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-63/srfi-63-1.7.html">2005-04-27</a></li> ++ <li>Final: 2005-04-27</li> ++</ul> ++ ++<h2>Abstract</h2> ++<p> + The SRFI, which is to supersede +-<A HREF="http://srfi.schemers.org/srfi-47/srfi-47.html">SRFI-47</A>, ++<a href="https://srfi.schemers.org/srfi-47/srfi-47.html">SRFI-47</a>, + "Array", ++</p> ++<ul> + +-<UL> +- +-<LI>synthesizes array concepts from Common-Lisp and Alan Bawden's ++<li>synthesizes array concepts from Common-Lisp and Alan Bawden's + "array.scm"; + +-</LI><LI>incorporates all the uniform vector types from +- <A HREF="http://srfi.schemers.org/srfi-4/srfi-4.html">SFRI-4</A> ++</li> ++<li>incorporates all the uniform vector types from ++ <a href="srfi-4.html">SFRI-4</a> + "Homogeneous numeric vector datatypes"; +- +-</LI><LI>adds a boolean uniform array type; +- +-</LI><LI>adds 16.bit and 128.bit floating-point uniform-array types; +- +-</LI><LI>adds decimal floating-point uniform-array types; and +- +-</LI><LI>adds array types of (dual) floating-point complex numbers. +- +-</LI></UL> +- ++</li> ++<li>adds a boolean uniform array type; ++</li> ++<li>adds 16.bit and 128.bit floating-point uniform-array types; ++</li> ++<li>adds decimal floating-point uniform-array types; and ++</li> ++<li>adds array types of (dual) floating-point complex numbers. ++</li> ++</ul> ++<p> + Multi-dimensional arrays subsume homogeneous vectors as the + one-dimensional case, obviating the need for SRFI-4. +-<P> ++</p> ++<p> + SRFI-58 gives a read/write invariant syntax for the homogeneous and + heterogeneous arrays described here. +-</P><P> ++</p> + +-</P><H1>Issues</H1> ++<h2>Issues</h2> + +-<UL> ++<ul> + <!-- <LI> --> + <!-- Character arrays can be supported based on strings; but they do not --> + <!-- necessarily have access times comparable to other types of arrays. --> + <!-- <P> --> +-<LI> +-The <A HREF="#Conversions">conversion rules</A> for exact decimal ++<li> ++<p> ++The <a href="#Conversions">conversion rules</a> for exact decimal + flonums have yet to be determined. Wisdom in this area would come + from experience. Lacking that, it is better to underspecify the + behavior of decimal flonums than to make it wrong. +-<P> + <!-- <LI> --> + <!-- <CODE>array->vector</CODE> and <CODE>vector->array</CODE> are --> + <!-- not inverses for rank-0 arrays. --> + <!-- <P> --> +-</P></LI></UL> ++</p> ++</li> ++</ul> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + +-<H2>Arrays</H2> ++<h3>Arrays</h3> + ++<p> + Computations have been organized into multidimensional arrays for over + 200 years. Applications for multi-dimensional arrays continue to + arise. Computer graphics and imaging, whether vector or raster based, + use arrays. A general-purpose computer language without + multidimensional arrays is an oxymoron. ++</p> + +-<H2>Precision</H2> ++<h3>Precision</h3> + ++<p> + R5RS provides an input syntax for inexact numbers which is capable of +-distinguishing between <VAR>short</VAR>, <VAR>single</VAR>, +-<VAR>double</VAR>, and <VAR>long</VAR> precisions. But R5RS provides ++distinguishing between <var>short</var>, <var>single</var>, ++<var>double</var>, and <var>long</var> precisions. But R5RS provides + no method for limiting the precision of calculations: ++</p> + +-<BLOCKQUOTE> ++<blockquote> + In particular, implementations that use flonum representations must + follow these rules: A flonum result must be represented with at least + as much precision as is used to express any of the inexact arguments + to that operation. ++</blockquote> + +-</BLOCKQUOTE> +- ++<p> + And calculation with any exact number inputs blows the precision out + to "the most precise flonum format available": ++</p> + +-<BLOCKQUOTE> ++<blockquote> + If, however, an exact number is operated upon so as to produce an +-inexact result (as by <SAMP>`sqrt'</SAMP>), and if the result is ++inexact result (as by <samp>`sqrt'</samp>), and if the result is + represented as a flonum, then the most precise flonum format available + must be used; but if the result is represented in some other way then + the representation must have at least as much precision as the most + precise flonum format available. ++</blockquote> + +-</BLOCKQUOTE> +- ++<p> + Scheme is not much hampered by lack of low-precision inexact numbers + for scalar calculations. The extra computation incurred by gratuitous + precision is usually small compared with the overhead of type-dispatch + and boxed data manipulation. +-<P> +-</P><H2>Homogeneous Arrays</H2> ++</p> ++ ++<h3>Homogeneous Arrays</h3> + ++<p> + But if calculations are vectorized, that overhead can become + significant. Sophisticated program analysis may be able to deduce + that aggregated number storage can be made uniformly of the most +@@ -136,7 +161,8 @@ precise flonum format available. But even the most aggressive + analysis of uncontrived programs will not be able to reduce the + precision while yielding results equivalent to the most precise + calculation, as R5RS requires. +-<P> ++</p> ++<p> + <!-- Globally reduced precision is a poor solution. The intermediate --> + <!-- results should be calculated with precision as high or higher than the --> + <!-- inputs, even if the results will be stored with lower precision. --> +@@ -146,26 +172,31 @@ implementations has manifest type information encoded with it. + Varying sizes of number objects means that the vectors hold pointers + to some numbers, requiring data fetches from memory locations unlikely + to be in the same CPU cache-line. +-</P><P> ++</p> ++<p> + Arrays composed of elements all having the same size representations + can eliminate these indirect accesses and the storage allocation + associated with them. Homogeneous arrays of lower precision flonums + can reduce by factors of 2 or 4 the storage they occupy; which can + also speed execution because of the lower bandwidth to the memory + necessary to supply the CPU data cache. +-</P><P> +-</P><H2>Common Lisp</H2> ++</p> ++ ++<h3>Common Lisp</h3> + ++<p> + Common-Lisp arrays are serviceable, and are the basis for arrays here. +-Common-Lisp's <CODE>make-array</CODE> does not translate well to ++Common-Lisp's <code>make-array</code> does not translate well to + Scheme because the array element type and the initial contents are + passed using named arguments. +-<P> ++</p> ++<p> + Prototype arrays specify both the homogeneous array type (or lack of) + and the initial value or lack of it; allowing these purposes to be +-satisfied by one argument to <CODE>make-array</CODE> or other ++satisfied by one argument to <code>make-array</code> or other + procedures which create arrays. +-</P><P> ++</p> ++<p> + Some have objected that restricting type specification to arrays is a + half-measure. In vectorized programs, specifying the precision of + scalar calculations will produce negligible performance improvements. +@@ -173,319 +204,408 @@ But the performance improvements of homogeneous arrays can accrue to + both interpreted and compiled Scheme implementations. By avoiding the + morass of general type specification, SRFI-63 can be more easily + accommodated by more Scheme implementations. +-</P><P> +-</P><H2>Argument Order</H2> ++</p> + +-<UL> +-<LI> ++<h3>Argument Order</h3> ++ ++<ul> ++<li> ++<p> + Most of the procedures originate from Alan Bawden's "array.scm". +-SRFI-47's <CODE>array-set!</CODE> argument order is that of Bawden's +-package. <a href="http://swissnet.ai.mit.edu/%7Ejaffer/SLIB">SLIB</A> +-adopted "array.scm" in 1993. This form of <CODE>array-set!</CODE> has ++SRFI-47's <code>array-set!</code> argument order is that of Bawden's ++package. <a href="http://swissnet.ai.mit.edu/~jaffer/SLIB">SLIB</a> ++adopted "array.scm" in 1993. This form of <code>array-set!</code> has + also been part of the +-<a href="http://swissnet.ai.mit.edu/%7Ejaffer/SCM">SCM</A> Scheme +-implementation since 1993.<P> +- +-</P></LI><LI> +-The <CODE>array-set!</CODE> argument order is different from the ++<a href="http://swissnet.ai.mit.edu/~jaffer/SCM">SCM</a> Scheme ++implementation since 1993. ++</p> ++</li> ++<li> ++<p> ++The <code>array-set!</code> argument order is different from the + same-named procedure in +-<A HREF="http://srfi.schemers.org/srfi-25/srfi-25.html">SRFI-25</A>. +-Type dispatch on the first argument to <CODE>array-set!</CODE> could +-support both SRFIs simultaneously.<P> +- +-</P></LI><LI> +-The <CODE>make-array</CODE> arguments are different from the ++<a href="srfi-25.html">SRFI-25</a>. ++Type dispatch on the first argument to <code>array-set!</code> could ++support both SRFIs simultaneously. ++</p> ++</li> ++<li> ++<p> ++The <code>make-array</code> arguments are different from the + same-named procedure in +-<A HREF="http://srfi.schemers.org/srfi-25/srfi-25.html">SRFI-25</A>. +-Type dispatch on the first argument to <CODE>make-array</CODE> could +-support both SRFIs simultaneously.<P> +- +-</P></LI><LI> ++<a href="srfi-25.html">SRFI-25</a>. ++Type dispatch on the first argument to <code>make-array</code> could ++support both SRFIs simultaneously. ++</p> ++</li> ++<li> ++<p> + The SRFI-47 argument orders are motivated to make easy dealing with + the variable arity resulting from variable rank. +- +-<PRE> (vector->array vect proto bound1 ...) ++</p> ++<pre> (vector->array vect proto bound1 ...) + (make-array proto bound1 ...) + (make-shared-array array mapper bound1 ...) + (array-set! array obj index1 ...) + (array-in-bounds? array index1 ...) + (array-ref array index1 ...) +-</PRE> +-<P> ++</pre> ++<p> + The list->array is somewhat dissonant: +-</P><PRE> (list->array rank proto list) +-</PRE> +-<P> +-</P></LI></UL> +-<P> ++</p> ++<pre> (list->array rank proto list) ++</pre> ++</li> ++</ul> + +-</P><H2>Homogeneous Array Types</H2> ++<h3>Homogeneous Array Types</h3> + ++<p> + All implementations must support Scheme strings as rank 1 character + arrays. This requirement mandates that Scheme strings be valid + arguments to array procedures; their stored representations may be + different from other character arrays. +-<P> +- ++</p> ++<p> + Although an implementation is required to define all the prototype + functions, it is not required to support all or even any of the + homogeneous numeric arrays. It is assumed that no uniform numeric + types have larger precision than the Scheme implementation supports as + numbers. +-</P><P> +-<A name="Table-1"></A> +-<TABLE border="1"> +-<TBODY><TR><th>prototype<br>procedure ++</p> ++<table border="1" id="Table-1"> ++<tbody><tr><th>prototype<br />procedure + </th><th>exactness + </th><th>element type +-</th></TR><TR><TD><CODE>vector </CODE></TD><TD> </TD><TD>any +-</TD></TR><TR><TD><CODE>A:floC128b</CODE></TD><TD>inexact</TD><TD>128.bit binary flonum complex +-</TD></TR><TR><TD><CODE>A:floC64b </CODE></TD><TD>inexact</TD><TD>64.bit binary flonum complex +-</TD></TR><TR><TD><CODE>A:floC32b </CODE></TD><TD>inexact</TD><TD>32.bit binary flonum complex +-</TD></TR><TR><TD><CODE>A:floC16b </CODE></TD><TD>inexact</TD><TD>16.bit binary flonum complex +-</TD></TR><TR><TD><CODE>A:floR128b</CODE></TD><TD>inexact</TD><TD>128.bit binary flonum real +-</TD></TR><TR><TD><CODE>A:floR64b </CODE></TD><TD>inexact</TD><TD>64.bit binary flonum real +-</TD></TR><TR><TD><CODE>A:floR32b </CODE></TD><TD>inexact</TD><TD>32.bit binary flonum real +-</TD></TR><TR><TD><CODE>A:floR16b </CODE></TD><TD>inexact</TD><TD>16.bit binary flonum real +-</TD></TR><TR><td colspan="3"> +-</TD></TR><TR><TD><CODE>A:floQ128d</CODE></TD><TD>exact</TD><TD>128.bit decimal flonum rational +-</TD></TR><TR><TD><CODE>A:floQ64d </CODE></TD><TD>exact</TD><TD>64.bit decimal flonum rational +-</TD></TR><TR><TD><CODE>A:floQ32d </CODE></TD><TD>exact</TD><TD>32.bit decimal flonum rational +-</TD></TR><TR><td colspan="3"> +-</TD></TR><TR><TD><CODE>A:fixZ64b </CODE></TD><TD>exact</TD><TD>64.bit binary fixnum +-</TD></TR><TR><TD><CODE>A:fixZ32b </CODE></TD><TD>exact</TD><TD>32.bit binary fixnum +-</TD></TR><TR><TD><CODE>A:fixZ16b </CODE></TD><TD>exact</TD><TD>16.bit binary fixnum +-</TD></TR><TR><TD><CODE>A:fixZ8b </CODE></TD><TD>exact</TD><TD>8.bit binary fixnum +-</TD></TR><TR><TD><CODE>A:fixN64b </CODE></TD><TD>exact</TD><TD>64.bit nonnegative binary fixnum +-</TD></TR><TR><TD><CODE>A:fixN32b </CODE></TD><TD>exact</TD><TD>32.bit nonnegative binary fixnum +-</TD></TR><TR><TD><CODE>A:fixN16b </CODE></TD><TD>exact</TD><TD>16.bit nonnegative binary fixnum +-</TD></TR><TR><TD><CODE>A:fixN8b </CODE></TD><TD>exact</TD><TD>8.bit nonnegative binary fixnum +-</TD></TR><TR><TD><CODE>A:bool </CODE></TD><TD> </TD><TD>boolean +-</TD></TR><TR><TD><CODE>string </CODE></TD><TD> </TD><TD>char +-</TD></TR></TBODY></TABLE> +-</P><P> ++</th></tr><tr><td><code>vector </code></td><td> </td><td>any ++</td></tr><tr><td><code>A:floC128b</code></td><td>inexact</td><td>128.bit binary flonum complex ++</td></tr><tr><td><code>A:floC64b </code></td><td>inexact</td><td>64.bit binary flonum complex ++</td></tr><tr><td><code>A:floC32b </code></td><td>inexact</td><td>32.bit binary flonum complex ++</td></tr><tr><td><code>A:floC16b </code></td><td>inexact</td><td>16.bit binary flonum complex ++</td></tr><tr><td><code>A:floR128b</code></td><td>inexact</td><td>128.bit binary flonum real ++</td></tr><tr><td><code>A:floR64b </code></td><td>inexact</td><td>64.bit binary flonum real ++</td></tr><tr><td><code>A:floR32b </code></td><td>inexact</td><td>32.bit binary flonum real ++</td></tr><tr><td><code>A:floR16b </code></td><td>inexact</td><td>16.bit binary flonum real ++</td></tr><tr><td colspan="3"> ++</td></tr><tr><td><code>A:floQ128d</code></td><td>exact</td><td>128.bit decimal flonum rational ++</td></tr><tr><td><code>A:floQ64d </code></td><td>exact</td><td>64.bit decimal flonum rational ++</td></tr><tr><td><code>A:floQ32d </code></td><td>exact</td><td>32.bit decimal flonum rational ++</td></tr><tr><td colspan="3"> ++</td></tr><tr><td><code>A:fixZ64b </code></td><td>exact</td><td>64.bit binary fixnum ++</td></tr><tr><td><code>A:fixZ32b </code></td><td>exact</td><td>32.bit binary fixnum ++</td></tr><tr><td><code>A:fixZ16b </code></td><td>exact</td><td>16.bit binary fixnum ++</td></tr><tr><td><code>A:fixZ8b </code></td><td>exact</td><td>8.bit binary fixnum ++</td></tr><tr><td><code>A:fixN64b </code></td><td>exact</td><td>64.bit nonnegative binary fixnum ++</td></tr><tr><td><code>A:fixN32b </code></td><td>exact</td><td>32.bit nonnegative binary fixnum ++</td></tr><tr><td><code>A:fixN16b </code></td><td>exact</td><td>16.bit nonnegative binary fixnum ++</td></tr><tr><td><code>A:fixN8b </code></td><td>exact</td><td>8.bit nonnegative binary fixnum ++</td></tr><tr><td><code>A:bool </code></td><td> </td><td>boolean ++</td></tr><tr><td><code>string </code></td><td> </td><td>char ++</td></tr></tbody></table> ++<p> + Decimal flonums are used for financial calculations so that fractional + errors do not accumulate. They should be exact numbers. +-</P><P> +-<A NAME="Conversions"></A> +-</P><H2>Conversions</H2> ++</p> + +-<UL> +-<LI> All the elements of arrays of type A:fixN8b, A:fixN16b, +- A:fixN32b, A:fixN64b, A:fixZ8b, A:fixZ16b, A:fixZ32b, or +- A:fixZ64b are exact.<P> ++<h3 id="Conversions">Conversions</h3> + +-</P></LI><LI> All the elements of arrays of type A:floR16b, A:floR32b, ++<ul> ++<li> ++ <p> ++ All the elements of arrays of type A:fixN8b, A:fixN16b, ++ A:fixN32b, A:fixN64b, A:fixZ8b, A:fixZ16b, A:fixZ32b, or ++ A:fixZ64b are exact. ++ </p> ++</li> ++<li> ++ <p> ++ All the elements of arrays of type A:floR16b, A:floR32b, + A:floR64b, A:floR128b, A:floC16b, A:floC32b, A:floC64b, and +- A:floC128b are inexact.<P> +- +-</P></LI><LI> The value retrieved from an exact array element will equal (=) +- the value stored in that element.<P> +- +-</P></LI><LI> Assigning a non-integer to array-type A:fixN8b, A:fixN16b, ++ A:floC128b are inexact. ++ </p> ++</li> ++<li> ++ <p> ++ The value retrieved from an exact array element will equal (=) ++ the value stored in that element. ++ </p> ++</li> ++<li> ++ <p> ++ Assigning a non-integer to array-type A:fixN8b, A:fixN16b, + A:fixN32b, A:fixN64b, A:fixZ8b, A:fixZ16b, A:fixZ32b, or +- A:fixZ64b is an error.<P> +- +-</P></LI><LI> Assigning a number larger than can be represented in array-type ++ A:fixZ64b is an error. ++ </p> ++</li> ++<li> ++ <p> ++ Assigning a number larger than can be represented in array-type + A:fixN8b, A:fixN16b, A:fixN32b, A:fixN64b, A:fixZ8b, A:fixZ16b, +- A:fixZ32b, or A:fixZ64b is an error.<P> +- +-</P></LI><LI> Assigning a negative number to array-type A:fixN8b, A:fixN16b, +- A:fixN32b, or A:fixN64b is an error.<P> +- +-</P></LI><LI> Assigning an inexact number to array-type A:fixN8b, A:fixN16b, ++ A:fixZ32b, or A:fixZ64b is an error. ++ </p> ++</li> ++<li> ++ <p> ++ Assigning a negative number to array-type A:fixN8b, A:fixN16b, ++ A:fixN32b, or A:fixN64b is an error. ++ </p> ++</li> ++<li> ++ <p> ++ Assigning an inexact number to array-type A:fixN8b, A:fixN16b, + A:fixN32b, A:fixN64b, A:fixZ8b, A:fixZ16b, A:fixZ32b, or +- A:fixZ64b is an error.<P> +- +-</P></LI><LI> When assigning an exact number to an inexact array-type, the ++ A:fixZ64b is an error. ++ </p> ++</li> ++<li> ++ <p> ++ When assigning an exact number to an inexact array-type, the + procedure may report a violation of an implementation +- restriction.<P> +- +-</P></LI><LI> Assigning a non-real number (eg. <CODE>real?</CODE> returns +- <CODE>#f</CODE>) to an A:floR128b, A:floR64b, A:floR32b, or +- A:floR16b array is an error.<P> +- +-</P></LI><LI> When an inexact number is assigned to an array whose type is ++ restriction. ++ </p> ++</li> ++<li> ++ <p> ++ Assigning a non-real number (eg. <code>real?</code> returns ++ <code>#f</code>) to an A:floR128b, A:floR64b, A:floR32b, or ++ A:floR16b array is an error. ++ </p> ++</li> ++<li> ++ <p> ++ When an inexact number is assigned to an array whose type is + lower precision, the number will be rounded to that lower +- precision if possible; otherwise it is an error.<P> ++ precision if possible; otherwise it is an error. ++ </p> ++</li> ++</ul> + +-</P></LI></UL> + +-<A NAME="Prototype Procedures"></A> +-<H2>Prototype Procedures</H2> ++<h3 id="Prototype%20Procedures">Prototype Procedures</h3> + ++<p> + Implementations are required to define all of the prototype + procedures. Uniform types of matching format and sizes which the + platform supports will be used; the others will be represented as + follows: +-<P> ++</p> ++<p> + For inexact flonum complex arrays: +-</P><UL> +- <LI>the next larger complex format is used; +- </LI><LI>if there is no larger format, +- <UL> +- <LI>then if the implementation supports complex floating-point numbers of ++</p> ++<ul> ++ <li> ++ the next larger complex format is used; ++ </li> ++ <li> ++ if there is no larger format, ++ <ul> ++ <li> ++ then if the implementation supports complex floating-point numbers of + unbounded precision, +- <UL> +- <LI>then a heterogeneous array; +- </LI><LI>else the largest inexact flonum complex array. +- </LI></UL> +- </LI></UL> +-</LI></UL> +- ++ <ul> ++ <li> ++ then a heterogeneous array; ++ </li> ++ <li> ++ else the largest inexact flonum complex array. ++ </li> ++ </ul> ++ </li> ++ </ul> ++ </li> ++</ul> ++<p> + For inexact flonum real arrays: +-<UL> +- <LI>the next larger real format is used; +- </LI><LI>if there is no larger real format, then the next larger complex format +- is used. +- </LI><LI>If there is no larger complex format, +- <UL> +- <LI>then if the implementation supports floating-point real numbers of ++</p> ++<ul> ++ <li> ++ the next larger real format is used; ++ </li> ++ <li> ++ if there is no larger real format, then the next larger complex format ++ is used. ++ </li> ++ <li> ++ If there is no larger complex format, ++ <ul> ++ <li> ++ then if the implementation supports floating-point real numbers of + unbounded precision, +- <UL> +- <LI>then a heterogeneous array; +- </LI><LI>else the largest inexact flonum real or complex array. +- </LI></UL> +- </LI></UL> +-</LI></UL> +- ++ <ul> ++ <li> ++ then a heterogeneous array; ++ </li> ++ <li> ++ else the largest inexact flonum real or complex array. ++ </li> ++ </ul> ++ </li> ++ </ul> ++ </li> ++</ul> ++<p> + For exact decimal flonum arrays: +-<UL> +- <LI>the next larger decimal flonum format array is used; +- </LI><LI>If there is no larger decimal flonum format, then a +- heterogeneous array is used. +-</LI></UL> +- ++</p> ++<ul> ++ <li> ++ the next larger decimal flonum format array is used; ++ </li> ++ <li> ++ If there is no larger decimal flonum format, then a ++ heterogeneous array is used. ++ </li> ++</ul> ++<p> + For exact bipolar fixnum arrays: +-<UL> +- <LI>the next larger bipolar fixnum format array is used; +- </LI><LI>If there is no larger bipolar fixnum format, +- <UL> +- <LI>then if the implementation supports exact integers of unbounded ++</p> ++<ul> ++ <li> ++ the next larger bipolar fixnum format array is used; ++ </li> ++ <li> ++ If there is no larger bipolar fixnum format, ++ <ul> ++ <li> ++ then if the implementation supports exact integers of unbounded + precision, +- <UL> +- <LI>then a heterogeneous array; +- </LI><LI>else the largest bipolar fixnum array. +- </LI></UL> +- </LI></UL> +-</LI></UL> +- ++ <ul> ++ <li> ++ then a heterogeneous array; ++ </li> ++ <li> ++ else the largest bipolar fixnum array. ++ </li> ++ </ul> ++ </li> ++ </ul> ++ </li> ++</ul> ++<p> + For exact nonnegative fixnum arrays: +-<UL> +- <LI>the next larger nonnegative fixnum format array is used; +- </LI><LI>If there is no larger nonnegative fixnum format, +- <UL> +- <LI>then the next larger bipolar fixnum format is used. +- </LI><LI>If there is no larger bipolar fixnum format, +- <UL> +- <LI>then if the implementation supports exact integers of +- unbounded precision, +- <UL> +- <LI>then a heterogeneous array; +- </LI><LI>else the largest nonnegative or bipolar fixnum array. +- </LI></UL> +- </LI></UL> +- </LI></UL> +-</LI></UL> +- +-<P> ++</p> ++<ul> ++ <li> ++ the next larger nonnegative fixnum format array is used; ++ </li> ++ <li> ++ If there is no larger nonnegative fixnum format, ++ <ul> ++ <li> ++ then the next larger bipolar fixnum format is used. ++ </li> ++ <li> ++ If there is no larger bipolar fixnum format, ++ <ul> ++ <li> ++ then if the implementation supports exact integers of ++ unbounded precision, ++ <ul> ++ <li> ++ then a heterogeneous array; ++ </li> ++ <li> ++ else the largest nonnegative or bipolar fixnum array. ++ </li> ++ </ul> ++ </li> ++ </ul> ++ </li> ++ </ul> ++ </li> ++</ul> ++ ++<p> + Note that these rules are used to configure an implementation's + definitions of the prototype procedures, which should not themselves + be type-dispatching. +-</P><P> ++</p> ++<p> + This arrangement has platforms which support uniform array types + employing them, with less capable platforms using vectors; but all + working compatibly from the same source code. +-</P><P> ++</p> + +-</P><H2>Shared Arrays</H2> ++<h3>Shared Arrays</h3> + ++<p> + To my knowledge, the specification of shared array index mapping by + means of a procedure is original to Alan Bawden in his "array.scm". +-<CODE>Make-shared-array</CODE> creates any view into an array whose ++<code>Make-shared-array</code> creates any view into an array whose + coordinates can be mapped by exact integer affine functions. The rank + of the arrays need not match. Shared arrays are quite useful. They + can reverse indexes, make subarrays, and facilitate straightforward + implementations of divide-and-conquer algorithms. +-<P> +-In Common-Lisp a <DFN>displaced array</DFN> can be created by calls to +-<A HREF="http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/fun_adjust-array.html">adjust-array</A>. ++</p> ++<p> ++In Common-Lisp a <dfn>displaced array</dfn> can be created by calls to ++<a href="http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/fun_adjust-array.html">adjust-array</a>. + +-But displaced arrays are far less flexible than <DFN>shared +-arrays</DFN>, constrained to have the same rank as the original and ++But displaced arrays are far less flexible than <dfn>shared ++arrays</dfn>, constrained to have the same rank as the original and + allowing only index displacements (not reversals, skips, or + shuffling). +-</P><P> ++</p> + +-</P><H2>Limit Cases</H2> ++<h3>Limit Cases</h3> + ++<p> + The bounds for each index in both Alan Bawden's "array.scm" and +-<A HREF="http://srfi.schemers.org/srfi-25/srfi-25.html">SRFI-25</A> +- ++<a href="srfi-25.html">SRFI-25</a> + can be any consecutive run of integers. All indexes in SRFI-63 are + zero-based for compatibility with R5RS. +-<P> ++</p> ++<p> + Empty arrays having no elements can be of any positive rank. Empty +-arrays can be returned from <CODE>make-shared-array</CODE>. +-</P><P> +-Following <A HREF="http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/sec_15-1-1-3.html">Common-Lisp</A>'s ++arrays can be returned from <code>make-shared-array</code>. ++</p> ++<p> ++Following <a href="http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/sec_15-1-1-3.html">Common-Lisp</a>'s + lead, zero-rank arrays have a single element. +-</P><P> ++</p> ++<p> + Except for character arrays, array access time is +-O(<I>R</I>)+<I>V</I>, where <I>R</I> is the rank of the array and +-<I>V</I> is the vector access time. +-</P><P> ++O(<i>R</i>)+<i>V</i>, where <i>R</i> is the rank of the array and ++<i>V</i> is the vector access time. ++</p> ++<p> + Character array access time is +-O(<I>R</I>)+<I>S</I>, where <I>R</I> is the rank of the array and +-<I>S</I> is the string access time. +-</P><P> +- +-</P><H1>Specification</H1> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array?</B> <I>obj</I> +-</DT><DD><A name="IDX1108"></A> +- +- +-<P> +-Returns <CODE>#t</CODE> if the <VAR>obj</VAR> is an array, and <CODE>#f</CODE> if not. +-</P></DD></DL> +- +- +-<P> +-<EM>Note:</EM> Arrays are not disjoint from other Scheme types. +-Vectors and possibly strings also satisfy <CODE>array?</CODE>. ++O(<i>R</i>)+<i>S</i>, where <i>R</i> is the rank of the array and ++<i>S</i> is the string access time. ++</p> ++ ++<h2>Specification</h2> ++ ++<dl> ++<dt><u>Function:</u> <b>array?</b> <i>obj</i> ++</dt> ++<dd id="IDX1108"> ++<p> ++Returns <code>#t</code> if the <var>obj</var> is an array, and <code>#f</code> if not. ++</p> ++<p> ++<em>Note:</em> Arrays are not disjoint from other Scheme types. ++Vectors and possibly strings also satisfy <code>array?</code>. + A disjoint array predicate can be written: +- +- +- +-</P><PRE>(define (strict-array? obj) ++</p> ++<pre>(define (strict-array? obj) + (and (array? obj) (not (string? obj)) (not (vector? obj)))) +-</PRE> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>equal?</B> <I>obj1 obj2</I> +-</DT><DD><A name="IDX1109"></A> +- +- +-<P> +-Returns <CODE>#t</CODE> if <VAR>obj1</VAR> and <VAR>obj2</VAR> have the same rank and dimensions and the +-corresponding elements of <VAR>obj1</VAR> and <VAR>obj2</VAR> are <CODE>equal?</CODE>. +- +- +-</P><P> +-<CODE>equal?</CODE> recursively compares the contents of pairs, vectors, strings, and +-<EM>arrays</EM>, applying <CODE>eqv?</CODE> on other objects such as numbers +-and symbols. A rule of thumb is that objects are generally <CODE>equal?</CODE> if +-they print the same. <CODE>equal?</CODE> may fail to terminate if its arguments are ++</pre> ++</dd> ++<dt><u>Function:</u> <b>equal?</b> <i>obj1 obj2</i> ++</dt> ++<dd id="IDX1109"> ++<p> ++Returns <code>#t</code> if <var>obj1</var> and <var>obj2</var> have the same rank and dimensions and the ++corresponding elements of <var>obj1</var> and <var>obj2</var> are <code>equal?</code>. ++</p> ++<p> ++<code>equal?</code> recursively compares the contents of pairs, vectors, strings, and ++<em>arrays</em>, applying <code>eqv?</code> on other objects such as numbers ++and symbols. A rule of thumb is that objects are generally <code>equal?</code> if ++they print the same. <code>equal?</code> may fail to terminate if its arguments are + circular data structures. +- +- +- +-</P><PRE>(equal? 'a 'a) => #t ++</p> ++<pre>(equal? 'a 'a) => #t + (equal? '(a) '(a)) => #t + (equal? '(a (b) c) + '(a (b) c)) => #t +@@ -499,77 +619,66 @@ circular data structures. + (make-array '#(foo) 3 3)) => #t + (equal? (lambda (x) x) + (lambda (y) y)) => <em>unspecified</em> +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array-rank</B> <I>obj</I> +-</DT><DD><A name="IDX1110"></A> ++</pre> ++</dd> ++</dl> + + +-<P> +-Returns the number of dimensions of <VAR>obj</VAR>. If <VAR>obj</VAR> is not an array, 0 is ++<dl> ++<dt><u>Function:</u> <b>array-rank</b> <i>obj</i> ++</dt> ++<dd id="IDX1110"> ++<p> ++Returns the number of dimensions of <var>obj</var>. If <var>obj</var> is not an array, 0 is + returned. +-</P></DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array-dimensions</B> <I>array</I> +-</DT><DD><A name="IDX1111"></A> +- +- +-<P> ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt><u>Function:</u> <b>array-dimensions</b> <i>array</i> ++</dt> ++<dd id="IDX1111"> ++<p> + Returns a list of dimensions. +- +- +- +-</P><PRE>(array-dimensions (make-array '#() 3 5)) ++</p> ++<pre>(array-dimensions (make-array '#() 3 5)) + => (3 5) +-</PRE> +- +-</DD></DL> ++</pre> ++</dd> ++</dl> + +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>make-array</B> <I>prototype k1 ...</I> +-</DT><DD><A name="IDX1112"></A> + + +-<P> +-Creates and returns an array of type <VAR>prototype</VAR> with dimensions <VAR>k1</VAR>, ... +-and filled with elements from <VAR>prototype</VAR>. <VAR>prototype</VAR> must be an array, vector, or ++<dl> ++<dt><u>Function:</u> <b>make-array</b> <i>prototype k1 ...</i> ++</dt> ++<dd id="IDX1112"> ++<p> ++Creates and returns an array of type <var>prototype</var> with dimensions <var>k1</var>, ... ++and filled with elements from <var>prototype</var>. <var>prototype</var> must be an array, vector, or + string. The implementation-dependent type of the returned array +-will be the same as the type of <VAR>prototype</VAR>; except if that would be a vector ++will be the same as the type of <var>prototype</var>; except if that would be a vector + or string with rank not equal to one, in which case some variety of + array will be returned. +- +- +-</P><P> +-If the <VAR>prototype</VAR> has no elements, then the initial contents of the returned ++</p> ++<p> ++If the <var>prototype</var> has no elements, then the initial contents of the returned + array are unspecified. Otherwise, the returned array will be filled +-with the element at the origin of <VAR>prototype</VAR>. +-</P></DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>make-shared-array</B> <I>array mapper k1 ...</I> +-</DT><DD><A name="IDX1114"></A> +- +- +-<P> +-<CODE>make-shared-array</CODE> can be used to create shared subarrays of other +-arrays. The <VAR>mapper</VAR> is a function that translates coordinates in +-the new array into coordinates in the old array. A <VAR>mapper</VAR> must be ++with the element at the origin of <var>prototype</var>. ++</p> ++</dd> ++<dt><u>Function:</u> <b>make-shared-array</b> <i>array mapper k1 ...</i> ++</dt> ++<dd id="IDX1114"> ++<p> ++<code>make-shared-array</code> can be used to create shared subarrays of other ++arrays. The <var>mapper</var> is a function that translates coordinates in ++the new array into coordinates in the old array. A <var>mapper</var> must be + linear, and its range must stay within the bounds of the old array, but + it can be otherwise arbitrary. A simple example: +- +- +- +-</P><PRE>(define fred (make-array '#(#f) 8 8)) ++</p> ++<pre>(define fred (make-array '#(#f) 8 8)) + (define freds-diagonal + (make-shared-array fred (lambda (i) (list i i)) 8)) + (array-set! freds-diagonal 'foo 3) +@@ -580,426 +689,414 @@ it can be otherwise arbitrary. A simple example: + 2 2)) + (array-ref freds-center 0 0) + => FOO +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>list->array</B> <I>rank proto list</I> +-</DT><DD><A name="IDX1115"></A> +- +- +-<P> +-<VAR>list</VAR> must be a rank-nested list consisting of all the elements, in ++</pre> ++</dd> ++<dt><u>Function:</u> <b>list->array</b> <i>rank proto list</i> ++</dt> ++<dd id="IDX1115"> ++<p> ++<var>list</var> must be a rank-nested list consisting of all the elements, in + row-major order, of the array to be created. +- +- +-</P><P> +-<CODE>list->array</CODE> returns an array of rank <VAR>rank</VAR> and type <VAR>proto</VAR> consisting of all the +-elements, in row-major order, of <VAR>list</VAR>. When <VAR>rank</VAR> is 0, <VAR>list</VAR> is the lone ++</p> ++<p> ++<code>list->array</code> returns an array of rank <var>rank</var> and type <var>proto</var> consisting of all the ++elements, in row-major order, of <var>list</var>. When <var>rank</var> is 0, <var>list</var> is the lone + array element; not necessarily a list. +- +- +- +-</P><PRE>(list->array 2 '#() '((1 2) (3 4))) ++</p> ++<pre>(list->array 2 '#() '((1 2) (3 4))) + => #2A((1 2) (3 4)) + (list->array 0 '#() 3) + => #0A 3 +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array->list</B> <I>array</I> +-</DT><DD><A name="IDX1116"></A> +- +- +-<P> ++</pre> ++</dd> ++<dt><u>Function:</u> <b>array->list</b> <i>array</i> ++</dt> ++<dd id="IDX1116"> ++<p> + Returns a rank-nested list consisting of all the elements, in +-row-major order, of <VAR>array</VAR>. In the case of a rank-0 array, <CODE>array->list</CODE> returns ++row-major order, of <var>array</var>. In the case of a rank-0 array, <code>array->list</code> returns + the single element. +- +- +- +-</P><PRE>(array->list #2A((ho ho ho) (ho oh oh))) ++</p> ++<pre>(array->list #2A((ho ho ho) (ho oh oh))) + => ((ho ho ho) (ho oh oh)) + (array->list #0A ho) + => ho +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>vector->array</B> <I>vect proto dim1 ...</I> +-</DT><DD><A name="IDX1117"></A> +- +- +-<P> +-<VAR>vect</VAR> must be a vector of length equal to the product of exact +-nonnegative integers <VAR>dim1</VAR>, .... +- +- +-</P><P> +-<CODE>vector->array</CODE> returns an array of type <VAR>proto</VAR> consisting of all the elements, in +-row-major order, of <VAR>vect</VAR>. In the case of a rank-0 array, <VAR>vect</VAR> has a ++</pre> ++</dd> ++<dt><u>Function:</u> <b>vector->array</b> <i>vect proto dim1 ...</i> ++</dt> ++<dd id="IDX1117"> ++<p> ++<var>vect</var> must be a vector of length equal to the product of exact ++nonnegative integers <var>dim1</var>, .... ++</p> ++<p> ++<code>vector->array</code> returns an array of type <var>proto</var> consisting of all the elements, in ++row-major order, of <var>vect</var>. In the case of a rank-0 array, <var>vect</var> has a + single element. +- +- +- +-</P><PRE>(vector->array #(1 2 3 4) #() 2 2) ++</p> ++<pre>(vector->array #(1 2 3 4) #() 2 2) + => #2A((1 2) (3 4)) + (vector->array '#(3) '#()) + => #0A 3 +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array->vector</B> <I>array</I> +-</DT><DD><A name="IDX1118"></A> +- +- +-<P> +-Returns a new vector consisting of all the elements of <VAR>array</VAR> in ++</pre> ++</dd> ++<dt><u>Function:</u> <b>array->vector</b> <i>array</i> ++</dt> ++<dd id="IDX1118"> ++<p> ++Returns a new vector consisting of all the elements of <var>array</var> in + row-major order. +- +- +- +-</P><PRE>(array->vector #2A ((1 2)( 3 4))) ++</p> ++<pre>(array->vector #2A ((1 2)( 3 4))) + => #(1 2 3 4) + (array->vector #0A ho) + => #(ho) +-</PRE> +- +-</DD></DL> +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array-in-bounds?</B> <I>array index1 ...</I> +-</DT><DD><A name="IDX1119"></A> +- +- +-<P> +-Returns <CODE>#t</CODE> if its arguments would be acceptable to +-<CODE>array-ref</CODE>. +-</P></DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>array-ref</B> <I>array k1 ...</I> +-</DT><DD><A name="IDX1120"></A> +- +- +-<P> +-Returns the (<VAR>k1</VAR>, ...) element of <VAR>array</VAR>. +-</P></DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Procedure:</U> <B>array-set!</B> <I>array obj k1 ...</I> +-</DT><DD><A name="IDX1121"></A> +- +- +-<P> +-Stores <VAR>obj</VAR> in the (<VAR>k1</VAR>, ...) element of <VAR>array</VAR>. The value returned +-by <CODE>array-set!</CODE> is unspecified. +-</P></DD></DL> +- +- +-<P> ++</pre> ++</dd> ++<dt><u>Function:</u> <b>array-in-bounds?</b> <i>array index1 ...</i> ++</dt> ++<dd id="IDX1119"> ++<p> ++Returns <code>#t</code> if its arguments would be acceptable to ++<code>array-ref</code>. ++</p> ++</dd> ++<dt><u>Function:</u> <b>array-ref</b> <i>array k1 ...</i> ++</dt> ++<dd id="IDX1120"> ++<p> ++Returns the (<var>k1</var>, ...) element of <var>array</var>. ++</p> ++</dd> ++<dt><u>Procedure:</u> <b>array-set!</b> <i>array obj k1 ...</i> ++</dt> ++<dd id="IDX1121"> ++<p> ++Stores <var>obj</var> in the (<var>k1</var>, ...) element of <var>array</var>. The value returned ++by <code>array-set!</code> is unspecified. ++</p> ++<p> + These functions return a prototypical uniform-array enclosing the + optional argument (which must be of the correct type). If the + uniform-array type is supported by the implementation, then it is + returned; defaulting to the next larger precision type; resorting + finally to vector. +- +- +-</P><P> +-</P><DL> +-<DT><U>Function:</U> <B>a:floc128b</B> <I>z</I> +-</DT><DD><A name="IDX1122"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:floc128b</b> +-</DT><DD><A name="IDX1123"></A> ++</p> ++</dd> ++<dt><u>Function:</u> <b>a:floc128b</b> <i>z</i> ++</dt> ++<dd id="IDX1122"> ++</dd> ++<dt><u>Function:</u> <b>a:floc128b</b> ++</dt> ++<dd id="IDX1123"> ++<p> + Returns an inexact 128.bit flonum complex uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:floc64b</B> <I>z</I> +-</DT><DD><A name="IDX1124"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:floc64b</b> +-</DT><DD><A name="IDX1125"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:floc64b</b> <i>z</i> ++</dt> ++<dd id="IDX1124"> ++</dd> ++<dt><u>Function:</u> <b>a:floc64b</b> ++</dt> ++<dd id="IDX1125"> ++<p> + Returns an inexact 64.bit flonum complex uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:floc32b</B> <I>z</I> +-</DT><DD><A name="IDX1126"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:floc32b</b> +-</DT><DD><A name="IDX1127"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:floc32b</b> <i>z</i> ++</dt> ++<dd id="IDX1126"> ++</dd> ++<dt><u>Function:</u> <b>a:floc32b</b> ++</dt> ++<dd id="IDX1127"> + Returns an inexact 32.bit flonum complex uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:floc16b</B> <I>z</I> +-</DT><DD><A name="IDX1128"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:floc16b</b> +-</DT><DD><A name="IDX1129"></A> ++</dd> ++</dl> ++ ++<dl> ++<dt><u>Function:</u> <b>a:floc16b</b> <i>z</i> ++</dt> ++<dd id="IDX1128"> ++</dd> ++<dt><u>Function:</u> <b>a:floc16b</b> ++</dt> ++<dd id="IDX1129"> ++<p> + Returns an inexact 16.bit flonum complex uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor128b</B> <I>z</I> +-</DT><DD><A name="IDX1130"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor128b</b> +-</DT><DD><A name="IDX1131"></A> ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor128b</b> <i>z</i> ++</dt> ++<dd id="IDX1130"> ++</dd> ++<dt><u>Function:</u> <b>a:flor128b</b> ++</dt> ++<dd id="IDX1131"> ++<p> + Returns an inexact 128.bit flonum real uniform-array prototype. +-</DD></DL> ++</p> ++</dd> ++</dl> + + +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor64b</B> <I>z</I> +-</DT><DD><A name="IDX1132"></A> ++<dl> ++<dt><u>Function:</u> <b>a:flor64b</b> <i>z</i> ++</dt><dd><a name="IDX1132"></a> + + +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor64b</b> +-</DT><DD><A name="IDX1133"></A> ++</dd> ++<dt><u>Function:</u> <b>a:flor64b</b> ++</dt><dd><a name="IDX1133"></a> + Returns an inexact 64.bit flonum real uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor32b</B> <I>z</I> +-</DT><DD><A name="IDX1134"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor32b</b> +-</DT><DD><A name="IDX1135"></A> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor32b</b> <i>z</i> ++</dt> ++<dd id="IDX1134"> ++</dd> ++<dt><u>Function:</u> <b>a:flor32b</b> ++</dt> ++<dd id="IDX1135"> ++<p> + Returns an inexact 32.bit flonum real uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor16b</B> <I>z</I> +-</DT><DD><A name="IDX1136"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor16b</b> +-</DT><DD><A name="IDX1137"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor16b</b> <i>z</i> ++</dt> ++<dd id="IDX1136"> ++</dd> ++<dt><u>Function:</u> <b>a:flor16b</b> ++</dt> ++<dd id="IDX1137"> ++<p> + Returns an inexact 16.bit flonum real uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor128b</B> <I>z</I> +-</DT><DD><A name="IDX1138"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor128b</b> +-</DT><DD><A name="IDX1139"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor128b</b> <i>z</i> ++</dt> ++<dd id="IDX1138"> ++</dd> ++<dt><u>Function:</u> <b>a:flor128b</b> ++</dt> ++<dd id="IDX1139"> ++<p> + Returns an exact 128.bit decimal flonum rational uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor64b</B> <I>z</I> +-</DT><DD><A name="IDX1140"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor64b</b> +-</DT><DD><A name="IDX1141"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor64b</b> <i>z</i> ++</dt> ++<dd id="IDX1140"> ++</dd> ++<dt><u>Function:</u> <b>a:flor64b</b> ++</dt> ++<dd id="IDX1141"> ++<p> + Returns an exact 64.bit decimal flonum rational uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:flor32b</B> <I>z</I> +-</DT><DD><A name="IDX1142"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:flor32b</b> +-</DT><DD><A name="IDX1143"></A> ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt><u>Function:</u> <b>a:flor32b</b> <i>z</i> ++</dt> ++<dd id="IDX1142"> ++</dd> ++<dt><u>Function:</u> <b>a:flor32b</b> ++</dt> ++<dd id="IDX1143"> ++<p> + Returns an exact 32.bit decimal flonum rational uniform-array prototype. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixz64b</B> <I>n</I> +-</DT><DD><A name="IDX1144"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixz64b</b> +-</DT><DD><A name="IDX1145"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixz64b</b> <i>n</i> ++</dt> ++<dd id="IDX1144"> ++</dd> ++<dt><u>Function:</u> <b>a:fixz64b</b> ++</dt> ++<dd id="IDX1145"> ++<p> + Returns an exact binary fixnum uniform-array prototype with at least + 64 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixz32b</B> <I>n</I> +-</DT><DD><A name="IDX1146"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixz32b</b> +-</DT><DD><A name="IDX1147"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixz32b</b> <i>n</i> ++</dt> ++<dd id="IDX1146"> ++</dd> ++<dt><u>Function:</u> <b>a:fixz32b</b> ++</dt> ++<dd id="IDX1147"> ++<p> + Returns an exact binary fixnum uniform-array prototype with at least + 32 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixz16b</B> <I>n</I> +-</DT><DD><A name="IDX1148"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixz16b</b> +-</DT><DD><A name="IDX1149"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixz16b</b> <i>n</i> ++</dt> ++<dd id="IDX1148"> ++</dd> ++<dt><u>Function:</u> <b>a:fixz16b</b> ++</dt> ++<dd id="IDX1149"> ++<p> + Returns an exact binary fixnum uniform-array prototype with at least + 16 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixz8b</B> <I>n</I> +-</DT><DD><A name="IDX1150"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixz8b</b> +-</DT><DD><A name="IDX1151"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixz8b</b> <i>n</i> ++</dt> ++<dd id="IDX1150"> ++</dd> ++<dt><u>Function:</u> <b>a:fixz8b</b> ++</dt> ++<dd id="IDX1151"> ++<p> + Returns an exact binary fixnum uniform-array prototype with at least + 8 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixn64b</B> <I>k</I> +-</DT><DD><A name="IDX1152"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixn64b</b> +-</DT><DD><A name="IDX1153"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixn64b</b> <i>k</i> ++</dt> ++<dd id="IDX1152"> ++</dd> ++<dt><u>Function:</u> <b>a:fixn64b</b> ++</dt> ++<dd id="IDX1153"> ++<p> + Returns an exact non-negative binary fixnum uniform-array prototype with at + least 64 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixn32b</B> <I>k</I> +-</DT><DD><A name="IDX1154"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixn32b</b> +-</DT><DD><A name="IDX1155"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixn32b</b> <i>k</i> ++</dt> ++<dd id="IDX1154"> ++</dd> ++<dt><u>Function:</u> <b>a:fixn32b</b> ++</dt> ++<dd id="IDX1155"> ++<p> + Returns an exact non-negative binary fixnum uniform-array prototype with at + least 32 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixn16b</B> <I>k</I> +-</DT><DD><A name="IDX1156"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixn16b</b> +-</DT><DD><A name="IDX1157"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixn16b</b> <i>k</i> ++</dt> ++<dd id="IDX1156"> ++</dd> ++<dt><u>Function:</u> <b>a:fixn16b</b> ++</dt> ++<dd id="IDX1157"> ++<p> + Returns an exact non-negative binary fixnum uniform-array prototype with at + least 16 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:fixn8b</B> <I>k</I> +-</DT><DD><A name="IDX1158"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:fixn8b</b> +-</DT><DD><A name="IDX1159"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:fixn8b</b> <i>k</i> ++</dt> ++<dd id="IDX1158"> ++</dd> ++<dt><u>Function:</u> <b>a:fixn8b</b> ++</dt> ++<dd id="IDX1159"> ++<p> + Returns an exact non-negative binary fixnum uniform-array prototype with at + least 8 bits of precision. +-</DD></DL> +- +- +-<P> +-</P><DL> +-<DT><U>Function:</U> <B>a:bool</B> <I>bool</I> +-</DT><DD><A name="IDX1160"></A> +- +- +-<P> +-</P></DD><DT><u>Function:</u> <b>a:bool</b> +-</DT><DD><A name="IDX1161"></A> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt><u>Function:</u> <b>a:bool</b> <i>bool</i> ++</dt> ++<dd id="IDX1160"> ++</dd> ++<dt><u>Function:</u> <b>a:bool</b> ++</dt> ++<dd id="IDX1161"> ++<p> + Returns a boolean uniform-array prototype. +-</DD></DL> ++</p> ++</dd> ++</dl> + + + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/array.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/array.scm</A> ++<p> ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/slib/slib/array.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/array.scm</a> + implements array procedures for R4RS or R5RS compliant Scheme +-implementations with <DFN>records</DFN> as implemented by +-<A HREF="http://savannah.gnu.org/cgi-bin/viewcvs/slib/slib/record.scm?rev=HEAD&content-type=text/vnd.viewcvs-markup">slib/record.scm</A> +-or <A HREF="http://srfi.schemers.org/srfi-9/srfi-9.html">SRFI-9</A>. +-"<CODE>array.scm</CODE>" redefines <CODE>equal?</CODE> to handle ++implementations with <dfn>records</dfn> as implemented by ++<a href="http://savannah.gnu.org/cgi-bin/viewcvs/slib/slib/record.scm?rev=HEAD&content-type=text%2Fvnd.viewcvs-markup">slib/record.scm</a> ++or <a href="srfi-9.html">SRFI-9</a>. ++"<code>array.scm</code>" redefines <code>equal?</code> to handle + arrays. +-<P> +-</P><PRE>;;;;"array.scm" Arrays for Scheme ++</p> ++<pre>;;;;"array.scm" Arrays for Scheme + ; Copyright (C) 2001, 2003 Aubrey Jaffer + ; + ;Permission to copy this software, to modify it, to redistribute it, +@@ -1481,12 +1578,11 @@ arrays. + ;;@args + ;;Returns a boolean uniform-array prototype. + (define A:bool (make-prototype-checker 'A:bool boolean? vector)) +-</PRE> ++</pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + <p>Copyright (C) 2005 Aubrey Jaffer</p> +- +-<P> ++<p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including +@@ -1494,10 +1590,12 @@ without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: +-</P><P> ++</p> ++<p> + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. +-</P><P> ++</p> ++<p> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@@ -1505,12 +1603,12 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-</P><P> +- </P><HR> +- <ADDRESS>Editor: <A HREF="mailto:srfi-editors@srfi.schemers.org">David Van Horn</A></ADDRESS> ++</p> ++<hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> + <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> + <!-- hhmts start --> +-Last modified: Thu Jan 27 09:30:33 EST 2005 ++Last modified: Sun Jan 28 13:40:18 MET 2007 + <!-- hhmts end --> +- </BODY> +-</HTML> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-64.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-64.html +index db939d6..cdab208 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-64.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-64.html +@@ -1,49 +1,58 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +-<html><head><title>SRFI 64: A Scheme API for test suites</title> +- +- +- ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-64 ┃ ++┃ Commit: 2aa1ed2ec7c6b1e6c2b4543b9ccb2ab4132c16fe ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 64: A Scheme API for test suites</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + <style type="text/css"> +- div.title h1 { font-size: small; color: blue } +- div.title { font-size: xx-large; color: blue; font-weight: bold } +- h1 { font-size: x-large; color: blue } +- h2 { font-size: large; color: blue } + /* So var inside pre gets same font as var in paragraphs. */ + var { font-family: monospace; } +-</style></head><body> +-<div class="title"> +-<h1>Title</h1> +-A Scheme API for test suites +-</div> +- +-<h1>Author</h1> +-<p>Per Bothner +-<code><a href="mailto:per@bothner.com"><per@bothner.com></a></code></p> ++</style> ++ </head> ++ ++<body> ++<h1>SRFI 64: A Scheme API for test suites</h1> + +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-It will remain in draft status until 2005/03/17, or as amended. To +-provide input on this SRFI, please <code> +-<a href="mailto:srfi%20minus%2064%20at%20srfi%20dot%20schemers%20dot%20org">mailto:srfi minus 64 at srfi dot schemers dot org</a></code>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access previous messages via +-<a href="http://srfi.schemers.org/srfi-64/mail-archive/maillist.html">the +-archive of the mailing list</a>. +-<p> +-</p><ul> +- <li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-64/srfi-64.html">2005/01/07</a></li> +- <li>Draft: 2005/01/28 - 2005/03/28</li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-64/srfi-64.html?rev=1.3">2005/10/18</a> +- </li><li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-64/srfi-64.html?rev=1.5">2006/02/24</a> +- </li><li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-64/srfi-64.html?rev=1.6">2006/06/18</a></li> ++<p>by Per Bothner<br /> ++<code><a href="mailto:per@bothner.com"><per@bothner.com></a></code></p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 64 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-64/srfi-64.html">https://srfi.schemers.org/srfi-64/srfi-64.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+64%20%20+at+srfi+dotschemers+dot+org">srfi-64 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-64">archive</a>.</p> ++<ul> ++ <li>Received: 2005-01-07</li> ++ <li>Draft: 2005-01-28--2005-03-28</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-64/srfi-64-1.3.html">2005-10-18</a> ++ </li><li>Revised: <a href="https://srfi.schemers.org/srfi-64/srfi-64-1.5.html">2006-02-24</a> ++ </li><li>Final: <a href="https://srfi.schemers.org/srfi-64/srfi-64-1.6.html">2006-06-18</a></li> ++ <li>Revised to fix errata: 2016-08-11</li> + </ul> +-<p></p> + + +-<h1>Abstract</h1> ++ ++<h2>Abstract</h2> + <p> + This defines an API for writing <dfn>test suites</dfn>, to make it easy + to portably test Scheme APIs, libraries, applications, and implementations. +@@ -52,7 +61,7 @@ in the context of a <dfn>test-runner</dfn>. This specifications + also supports writing new test-runners, to allow customization + of reporting and processing the result of running test suites.</p> + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + + <p>The Scheme community needs a standard for writing test suites. + Every SRFI or other library should come with a test suite. +@@ -91,18 +100,19 @@ as functions or macros or built-ins. The reason for specifying them as + syntax is to allow specific tests to be skipped without evaluating sub-expressions, or for implementations + to add features such as printing line numbers or catching exceptions.</p> + +-<h1>Specification</h1> ++<h2>Specification</h2> + + <p>While this is a moderately complex specification, + you should be able to write simple test suites after just reading the + first few sections below. More advanced functionality, such + as writing a custom test-runner, is at the end of the specification.</p> + +-<h2>Writing basic test suites</h2> ++<h3>Writing basic test suites</h3> + <p>Let's start with a simple example. + This is a complete self-contained test-suite.</p> + +-<pre>;; Initialize and give a name to a simple testsuite. ++<pre> ++;; Initialize and give a name to a simple testsuite. + (test-begin "vec-test") + (define v (make-vector 5 99)) + ;; Require that an expression evaluate to true. +@@ -132,12 +142,13 @@ tests to be executed using an implementation-specified default test runner, + and <code>test-end</code> will cause a summary to be displayed + in an implementation-specified manner.</p> + +-<h3>Simple test-cases</h3> ++<h4>Simple test-cases</h4> + <p> + Primitive test cases test that a given condition is true. + They may have a name. + The core test case form is <code>test-assert</code>:</p> +-<pre>(<b>test-assert</b> [<var>test-name</var>] <var>expression</var>) ++<pre> ++(<b>test-assert</b> [<var>test-name</var>] <var>expression</var>) + </pre> + <p> + This evaluates the <var>expression</var>. +@@ -156,39 +167,46 @@ if there is no current test runner.</p> + <p> + The following forms may be more convenient than + using <code>test-assert</code> directly:</p> +-<pre>(<b>test-eqv</b> [<var>test-name</var>] <var>expected</var> <var>test-expr</var>) ++<pre> ++(<b>test-eqv</b> [<var>test-name</var>] <var>expected</var> <var>test-expr</var>) + </pre> + <p> + This is equivalent to:</p> +-<pre>(test-assert [<var>test-name</var>] (eqv? <var>expected</var> <var>test-expr</var>)) ++<pre> ++(test-assert [<var>test-name</var>] (eqv? <var>expected</var> <var>test-expr</var>)) + </pre> + <p> + Similarly <code>test-equal</code> and <code>test-eq</code> + are shorthand for <code>test-assert</code> combined with + <code>equal?</code> or <code>eq?</code>, respectively:</p> +-<pre>(<b>test-equal</b> [<var>test-name</var>] <var>expected</var> <var>test-expr</var>) ++<pre> ++(<b>test-equal</b> [<var>test-name</var>] <var>expected</var> <var>test-expr</var>) + (<b>test-eq</b> [<var>test-name</var>] <var>expected</var> <var>test-expr</var>)</pre> + <p> + Here is a simple example:</p> +-<pre>(define (mean x y) (/ (+ x y) 2.0)) ++<pre> ++(define (mean x y) (/ (+ x y) 2.0)) + (test-eqv 4 (mean 3 5)) + </pre> + <p>For testing approximate equality of inexact reals + we can use <code>test-approximate</code>:</p> +-<pre>(<b>test-approximate</b> [test-name] expected test-expr error) ++<pre> ++(<b>test-approximate</b> [test-name] expected test-expr error) + </pre> + <p> + This is equivalent to (except that each argument is only evaluated once):</p> +-<pre>(test-assert [test-name] ++<pre> ++(test-assert [test-name] + (and (>= test-expr (- expected error)) + (<= test-expr (+ expected error)))) + </pre> + +-<h3>Tests for catching errors</h3> ++<h4>Tests for catching errors</h4> + <p> + We need a way to specify that evaluation <em>should</em> fail. + This verifies that errors are detected when required.</p> +-<pre>(<b>test-error</b> [[<var>test-name</var>] <var>error-type</var>] <var>test-expr</var>) ++<pre> ++(<b>test-error</b> [[<var>test-name</var>] <var>error-type</var>] <var>test-expr</var>) + </pre> + <p> + Evaluating <var>test-expr</var> is expected to signal an error. +@@ -197,33 +215,36 @@ The kind of error is indicated by <var>error-type</var>.</p> + If the <var>error-type</var> is left out, or it is + <code>#t</code>, it means "some kind of unspecified error should be signaled". + For example:</p> +-<pre>(test-error #t (vector-ref '#(1 2) 9)) ++<pre> ++(test-error #t (vector-ref '#(1 2) 9)) + </pre> + <p> + This specification leaves it implementation-defined (or for a future + specification) what form <code><var>test-error</var></code> may take, + though all implementations must allow <code>#t</code>. + Some implementations may support +-<a href="http://srfi.schemers.org/srfi-35/srfi-35.html">SRFI-35's conditions</a>, ++<a href="srfi-35.html">SRFI-35's conditions</a>, + but these are only standardized for +-<a href="http://srfi.schemers.org/srfi-36/srfi-36.html">SRFI-36's I/O conditions</a>, which are seldom useful in test suites. ++<a href="https://srfi.schemers.org/srfi-36/srfi-36.html">SRFI-36's I/O conditions</a>, which are seldom useful in test suites. + An implementation may also allow implementation-specific + <q>exception types</q>. + For example Java-based implementations may allow + the names of Java exception classes:</p> +-<pre>;; Kawa-specific example ++<pre> ++;; Kawa-specific example + (test-error <java.lang.IndexOutOfBoundsException> (vector-ref '#(1 2) 9)) + </pre> + <p> + An implementation that cannot catch exceptions should skip + <code>test-error</code> forms.</p> + +-<h3>Testing syntax</h3> ++<h4>Testing syntax</h4> + <p> + Testing syntax is tricky, especially if we want to + check that invalid syntax is causes an error. + The following utility function can help:</p> +-<pre>(<b>test-read-eval-string</b> <var>string</var>) ++<pre> ++(<b>test-read-eval-string</b> <var>string</var>) + </pre> + <p> + This function parses <var>string</var> (using <code>read</code>) +@@ -231,16 +252,17 @@ and evaluates the result. + The result of evaluation is returned from <code>test-read-eval-string</code>. + An error is signalled if there are unread characters after the + <code>read</code> is done. +-For example:<br> +-<code>(test-read-eval-string "(+ 3 4)")</code> <i>evaluates to</i> <code>7</code>.<br> +-<code>(test-read-eval-string "(+ 3 4")</code> <i>signals an error</i>.<br> ++For example:<br /> ++<code>(test-read-eval-string "(+ 3 4)")</code> <i>evaluates to</i> <code>7</code>.<br /> ++<code>(test-read-eval-string "(+ 3 4")</code> <i>signals an error</i>.<br /> + <code>(test-read-eval-string "(+ 3 4) ")</code> <i>signals an error</i>, + because there is extra <q>junk</q> (<i>i.e.</i> a space) after the + list is read. + </p> + <p> + The <code>test-read-eval-string</code> used in tests:</p> +-<pre>(test-equal 7 (test-read-eval-string "(+ 3 4)")) ++<pre> ++(test-equal 7 (test-read-eval-string "(+ 3 4)")) + (test-error (test-read-eval-string "(+ 3")) + (test-equal #\newline (test-read-eval-string "#\\newline")) + (test-error (test-read-eval-string "#\\newlin")) +@@ -251,7 +273,7 @@ The <code>test-read-eval-string</code> used in tests:</p> + (test-equal '(x z) (test-read-string "(list 'x #;'y 'z)")) + </pre> + +-<h3>Test groups and paths</h3> ++<h4>Test groups and paths</h4> + <p>A <dfn>test group</dfn> is a named sequence of forms containing testcases, + expressions, and definitions. + Entering a group sets the <dfn>test group name</dfn>; leaving a +@@ -265,7 +287,8 @@ Scheme values, nor are they syntactic forms.</p> + A test group may contain nested inner test groups. + The <dfn>test group path</dfn> is a list of the currently-active + (entered) test group names, oldest (outermost) first.</p> +-<pre>(<b>test-begin</b> <var>suite-name</var> [<var>count</var>]) ++<pre> ++(<b>test-begin</b> <var>suite-name</var> [<var>count</var>]) + </pre> + <p>A <code>test-begin</code> enters a new test group. + The <var>suite-name</var> becomes the current test group name, +@@ -286,7 +309,8 @@ get executed because of some unexpected error.</p> + <p> + Additionally, if there is no currently executing test runner, + one is installed in an implementation-defined manner.</p> +-<pre>(<b>test-end</b> [<var>suite-name</var>]) ++<pre> ++(<b>test-end</b> [<var>suite-name</var>]) + </pre> + <p> + A <code>test-end</code> leaves the current test group. +@@ -301,11 +325,13 @@ installed a new test-runner, then the <code>test-end</code> + will de-install it, after reporting the accumulated test + results in an implementation-defined manner.</p> + +-<pre>(<b>test-group</b> <var>suite-name</var> <var>decl-or-expr</var> ...) ++<pre> ++(<b>test-group</b> <var>suite-name</var> <var>decl-or-expr</var> ...) + </pre> + <p> + Equivalent to:</p> +-<pre>(if (not (test-to-skip% <var>suite-name</var>)) ++<pre> ++(if (not (test-to-skip% <var>suite-name</var>)) + (dynamic-wind + (lambda () (test-begin <var>suite-name</var>)) + (lambda () <var>decl-or-expr</var> ...) +@@ -316,8 +342,9 @@ within the named test group. However, the entire group is skipped + if it matched an active <code>test-skip</code> (see later). + Also, the <code>test-end</code> is executed in case of an exception.</p> + +-<h3>Handling set-up and cleanup</h3> +-<pre>(<b>test-group-with-cleanup</b> <var>suite-name</var> ++<h4>Handling set-up and cleanup</h4> ++<pre> ++(<b>test-group-with-cleanup</b> <var>suite-name</var> + <var>decl-or-expr</var> ... + <var>cleanup-form</var>) + </pre> +@@ -329,14 +356,16 @@ The latter should be executed even if + one of a <code><var>decl-or-expr</var></code> forms raises an exception + (assuming the implementation has a way to catch exceptions).</p> + <p>For example:</p> +-<pre>(test-group-with-cleanup "test-file" +- (define f (open-output-file "log")) +- (do-a-bunch-of-tests f) +- (close-output-port f)) ++<pre> ++(let ((f (open-output-file "log"))) ++ (test-group-with-cleanup "test-file" ++ (do-a-bunch-of-tests f) ++ (close-output-port f))) + </pre> +- ++<p><b>Erratum note:</b> <a href="https://github.com/scheme-requests-for-implementation/srfi-64/blob/4470ffdec71b1cf61633b664958a3ce5e6997710/srfi-64.html">Earlier versions</a> had a non-working example. ++</p> + <!-- +-<h2>Test suites</h2> ++<h3>Test suites</h3> + <p> + <i>(Not sure how useful this is, given <code>test-group</code>).</i> + <p>A <dfn>test suite</dfn> is a test group that can (and must) be +@@ -358,12 +387,12 @@ You can run previously registered test suite: + </pre> + --> + +-<h2>Conditonal test-suites and other advanced features</h2> ++<h3>Conditonal test-suites and other advanced features</h3> + <p> + The following describes features for controlling which tests to execute, + or specifing that some tests are <em>expected</em> to fail.</p> + +-<h3>Test specifiers</h3> ++<h4>Test specifiers</h4> + <p>Sometimes we want to only run certain tests, or we know that + certain tests are expected to fail. + A <dfn>test specifier</dfn> is one-argument function that takes a test-runner +@@ -374,16 +403,17 @@ which is coerced to a specifier procedure, as described below for + <code><var>count</var></code> and <code><var>name</var></code>.</p> + <p> + A simple example is:</p> +-<pre>(if <var>some-condition</var> ++<pre> ++(if <var>some-condition</var> + (test-skip 2)) ;; skip next 2 tests + </pre> + <p> +-<code>(<b>test-match-name</b> <var>name</var>)</code><br> ++<code>(<b>test-match-name</b> <var>name</var>)</code><br /> + The resulting specifier matches if the current test name (as + returned by <code>test-runner-test-name</code>) is <code>equals?</code> to + <var>name</var>.</p> + <p> +-<code>(<b>test-match-nth</b> <var>n</var> [<var>count</var>])</code><br> ++<code>(<b>test-match-nth</b> <var>n</var> [<var>count</var>])</code><br /> + This evaluates to a <em>stateful</em> predicate: A counter keeps track of + how many times it has been called. + The predicate matches the <var>n</var>'th time it is called +@@ -391,29 +421,30 @@ The predicate matches the <var>n</var>'th time it is called + the next <code>(- <var>count</var> 1)</code> times, + where <var>count</var> defaults to <code>1</code>.</p> + <p> +-<code>(<b>test-match-any</b> <var>specifier</var> ...)</code><br> ++<code>(<b>test-match-any</b> <var>specifier</var> ...)</code><br /> + The resulting specifier matches if any <var>specifier</var> + matches. + Each <code><var>specifier</var></code> is applied, in order, + so side-effects from a later <code><var>specifier</var></code> happen + even if an earlier <code><var>specifier</var></code> is true.</p> + <p> +-<code>(<b>test-match-all</b> <var>specifier</var> ...)</code><br> ++<code>(<b>test-match-all</b> <var>specifier</var> ...)</code><br /> + The resulting specifier matches if each <var>specifier</var> + matches. + Each <code><var>specifier</var></code> is applied, in order, + so side-effects from a later <code><var>specifier</var></code> happen + even if an earlier <code><var>specifier</var></code> is false.</p> + <p> +-<code><var>count</var> </code><i>(i.e. an integer)</i><br> ++<code><var>count</var> </code><i>(i.e. an integer)</i><br /> + Convenience short-hand for: <code>(test-match-nth 1 <var>count</var>)</code>.</p> + <p> +-<code><var>name</var> </code><i>(i.e. a string)</i><br> ++<code><var>name</var> </code><i>(i.e. a string)</i><br /> + Convenience short-hand for <code>(test-match-name <var>name</var>)</code>.</p> + +-<h3>Skipping selected tests</h3> ++<h4>Skipping selected tests</h4> + <p>In some cases you may want to skip a test.</p> +-<pre>(<b>test-skip</b> <var>specifier</var>) ++<pre> ++(<b>test-skip</b> <var>specifier</var>) + </pre> + <p>Evaluating <code>test-skip</code> adds the + resulting <var>specifier</var> +@@ -425,40 +456,44 @@ If any specifier matches, then the test is skipped.</p> + For convenience, if the <var>specifier</var> is a string that + is syntactic sugar for <code>(test-match-name <var>specifier</var>)</code>. + For example:</p> +-<pre>(test-skip "test-b") ++<pre> ++(test-skip "test-b") + (test-assert "test-a") ;; executed + (test-assert "test-b") ;; skipped + </pre> + <p> + Any skip specifiers introduced by a <code>test-skip</code> + are removed by a following non-nested <code>test-end</code>.</p> +-<pre>(test-begin "group1") ++<pre> ++(test-begin "group1") + (test-skip "test-a") + (test-assert "test-a") ;; skipped + (test-end "group1") ;; Undoes the prior test-skip + (test-assert "test-a") ;; executed + </pre> + +-<h3>Expected failures</h3> ++<h4>Expected failures</h4> + <p> + Sometimes you know a test case will fail, but you don't have time + to or can't fix it. Maybe a certain feature only works on certain platforms. + However, you want the test-case to be there + to remind you to fix it. You want to note that + such tests are expected to fail.</p> +-<pre>(<b>test-expect-fail</b> <var>specifier</var>) ++<pre> ++(<b>test-expect-fail</b> <var>specifier</var>) + </pre> + <p> + Matching tests (where matching is defined as in <code>test-skip</code>) + are expected to fail. This only affects test reporting, + not test execution. For example:</p> +-<pre>(test-expect-fail 2) ++<pre> ++(test-expect-fail 2) + (test-eqv ...) ;; expected to fail + (test-eqv ...) ;; expected to fail + (test-eqv ...) ;; expected to pass + </pre> + +-<h2>Test-runner</h2> ++<h3>Test-runner</h3> + <p> + A <dfn>test-runner</dfn> is an object that runs a test-suite, + and manages the state. The test group path, and the sets skip and +@@ -466,39 +501,39 @@ expected-fail specifiers are part of the test-runner. + A test-runner will also typically accumulate statistics about executed tests, + </p> + <p> +-<code>(<b>test-runner?</b> <var>value</var>)</code><br> ++<code>(<b>test-runner?</b> <var>value</var>)</code><br /> + True iff <code><var>value</var></code> is a test-runner object.</p> + <p> +-<code>(<b>test-runner-current</b>)</code><br> +-<code>(<b>test-runner-current</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-current</b>)</code><br /> ++<code>(<b>test-runner-current</b> <var>runner</var>)</code><br /> + Get or set the current test-runner. + If an implementation supports parameter objects +-(as in <a href="http://srfi.schemers.org/srfi-39/srfi-39.html">SRFI-39</a>), ++(as in <a href="srfi-39.html">SRFI-39</a>), + then <code>test-runner-current</code> can be a parameter object. + Alternatively, <code>test-runner-current</code> may be implemented + as a macro or function + that uses a fluid or thread-local variable, or a plain global variable.</p> + <p> +-<code>(<b>test-runner-get</b>)</code><br> +-Same as <code>(test-runner-current)</code>, buth trows an exception ++<code>(<b>test-runner-get</b>)</code><br /> ++Same as <code>(test-runner-current)</code>, buth throws an exception + if there is no current test-runner.</p> + <p> +-<code>(<b>test-runner-simple</b>)</code><br> ++<code>(<b>test-runner-simple</b>)</code><br /> + Creates a new simple test-runner, that prints errors and a summary + on the standard output port.</p> + <p> +-<code>(<b>test-runner-null</b>)</code><br> ++<code>(<b>test-runner-null</b>)</code><br /> + Creates a new test-runner, that does nothing with the test results. + This is mainly meant for extending when writing a custom runner.</p> + <p> + Implementations <em>may</em> provide other test-runners, perhaps + a <code>(test-runner-gui)</code>.</p> +-<p><code>(<b>test-runner-create</b>)</code><br> ++<p><code>(<b>test-runner-create</b>)</code><br /> + Create a new test-runner. Equivalent to + <code>((test-runner-factory))</code>.</p> + <p> +-<code>(<b>test-runner-factory</b>)</code><br> +-<code>(<b>test-runner-factory</b> <var>factory</var>)</code><br> ++<code>(<b>test-runner-factory</b>)</code><br /> ++<code>(<b>test-runner-factory</b> <var>factory</var>)</code><br /> + Get or set the current test-runner factory. + A factory is a zero-argument function that creates a new test-runner. + The default value is <code>test-runner-simple</code>, +@@ -506,9 +541,9 @@ but implementations may provide a way to override the default. + As with <code>test-runner-current</code>, this may be a parameter object, + or use a per-thread, fluid, or global variable.</p> + +-<h3>Running specific tests with a specified runner</h3> ++<h4>Running specific tests with a specified runner</h4> + <p> +-<code>(<b>test-apply</b> [<var>runner</var>] <var>specifier</var> ... <var>procedure</var>)</code><br> ++<code>(<b>test-apply</b> [<var>runner</var>] <var>specifier</var> ... <var>procedure</var>)</code><br /> + Calls <var>procedure</var> with no arguments using the specified + <var>runner</var> as the current test-runner. + If <var>runner</var> is omitted, +@@ -521,16 +556,16 @@ if it matches any of the <var>specifier</var>s in the + <code>test-apply</code> <em>and</em> does not match any + active <code>test-skip</code> specifiers.</p> + <p> +-<code>(<b>test-with-runner </b><var>runner</var> <var>decl-or-expr</var> ...)</code><br> ++<code>(<b>test-with-runner </b><var>runner</var> <var>decl-or-expr</var> ...)</code><br /> + Executes each <var>decl-or-expr</var> in order in a context + where the current test-runner is <var>runner</var>.</p> + +-<h2>Test results</h2> ++<h3>Test results</h3> + <p>Running a test sets various status properties in the current test-runner. + This can be examined by a custom test-runner, + or (more rarely) in a test-suite.</p> + +-<h3>Result kind</h3> ++<h4>Result kind</h4> + <p>Running a test may yield one of the following + status symbols:</p> + <dl> +@@ -541,7 +576,7 @@ status symbols:</p> + <dt><code>'skip</code></dt><dd>The test was skipped.</dd> + </dl> + <p> +-<code>(<b>test-result-kind</b> [<var>runner</var>])</code><br> ++<code>(<b>test-result-kind</b> [<var>runner</var>])</code><br /> + Return one of the above result codes from the most recent tests. + Returns <code>#f</code> if no tests have been run yet. + If we've started on a new test, but don't have a result yet, +@@ -549,13 +584,13 @@ then the result kind is <code>'xfail</code> is the test is expected to fail, + <code>'skip</code> is the test is supposed to be skipped, + or <code>#f</code> otherwise.</p> + <p> +-<code>(<b>test-passed?</b> [<var>runner</var>])</code><br> ++<code>(<b>test-passed?</b> [<var>runner</var>])</code><br /> + True if the value of <code>(test-result-kind [<var>runner</var>])</code> + is one of <code>'pass</code> or <code>'xpass</code>. + This is a convenient shorthand that might be useful + in a test suite to only run certain tests if the previous test passed.</p> + +-<h3>Test result properties</h3> ++<h4>Test result properties</h4> + <p> + A test runner also maintains a set of more detailed <q>result properties</q> + associated with the current or most recent test. (I.e. the properties of the +@@ -564,44 +599,44 @@ Each property has a name (a symbol) and a value (any value). + Some properties are standard or set by the implementation; + implementations can add more.</p> + <p> +-<code>(<b>test-result-ref</b> <var>runner</var> '<var>pname</var> [<var>default</var>])</code><br> ++<code>(<b>test-result-ref</b> <var>runner</var> '<var>pname</var> [<var>default</var>])</code><br /> + Returns the property value associated with the <var>pname</var> property name. + If there is no value associated with <code>'<var>pname</var></code> + return <var>default</var>, + or <code>#f</code> if <var>default</var> isn't specified.</p> + <p> +-<code>(<b>test-result-set!</b> <var>runner</var> '<var>pname</var> <var>value</var>)</code><br> ++<code>(<b>test-result-set!</b> <var>runner</var> '<var>pname</var> <var>value</var>)</code><br /> + Sets the property value associated with the <var>pname</var> + property name to <var>value</var>. + Usually implementation code should call this function, but it may be + useful for a custom test-runner to add extra properties.</p> + <p> +-<code>(<b>test-result-remove</b> <var>runner</var> '<var>pname</var>)</code><br> ++<code>(<b>test-result-remove</b> <var>runner</var> '<var>pname</var>)</code><br /> + Remove the property with the name <code>'<var>pname</var></code>.</p> + <p> +-<code>(<b>test-result-clear</b> <var>runner</var>)</code><br> ++<code>(<b>test-result-clear</b> <var>runner</var>)</code><br /> + Remove all result properties. + The implementation automatically calls <code>test-result-clear</code> + at the start of a <code>test-assert</code> and similar procedures.</p> + <p> +-<code>(<b>test-result-alist</b> <var>runner</var>)</code><br> ++<code>(<b>test-result-alist</b> <var>runner</var>)</code><br /> + Returns an association list of the current result properties. + It is unspecified if the result shares state with the test-runner. + The result should not be modified, on the other hand the result + may be implicitly modified by future <code>test-result-set!</code> or + <code>test-result-remove</code> calls. +-However, A <code>test-result-clear</code> does not modify the returned ++However, a <code>test-result-clear</code> does not modify the returned + alist. Thus you can <q>archive</q> result objects from previous runs.</p> + +-<h3>Standard result properties</h3> ++<h4>Standard result properties</h4> + <p> + The set of available result properties is implementation-specific. + However, it is suggested that the following might be provided:</p> + <dl> + <dt><code>'result-kind</code></dt> + <dd>The result kind, as defined previously. +-This is the only mandatory result property.<br> +-<code>(test-result-kind <var>runner</var>)</code> is equivalent to:<br> ++This is the only mandatory result property.<br /> ++<code>(test-result-kind <var>runner</var>)</code> is equivalent to:<br /> + <code>(test-result-ref <var>runner</var> 'result-kind)</code> + </dd> + <dt><code>'source-file</code></dt> +@@ -622,12 +657,12 @@ specified in a <code>test-error</code>, if it meaningful and known.</dd> + The actual error value is implementation-defined.</dd> + </dl> + +-<h2>Writing a new test-runner</h2> ++<h3>Writing a new test-runner</h3> + <p>This section specifies how to write a test-runner. + It can be ignored if you just want to write test-cases.</p> + + +-<h3>Call-back functions</h3> ++<h4>Call-back functions</h4> + <p> + These call-back functions are <q>methods</q> (in the object-oriented sense) + of a test-runner. A method <code>test-runner-on-<var>event</var></code> +@@ -635,66 +670,66 @@ is called by the implementation when <var>event</var> happens.</p> + <p> + To define (set) the callback function for <var>event</var> use the following expression. + (This is normally done when initializing a test-runner.) +-<br> ++<br /> + <code>(test-runner-on-<var>event</var>! <var>runner</var> <var>event-function</var>)</code></p> + <p> + An <var>event-function</var> takes a test-runner argument, and possibly other arguments, depending on the <var>event</var>.</p> + <p> +-To extract (get) the callback function for <var>event</var> do this:<br> ++To extract (get) the callback function for <var>event</var> do this:<br /> + <code>(test-runner-on-<var>event</var> <var>runner</var>)</code></p> + <p> + To extract call the callback function for <var>event</var> use the following expression. +-(This is normally done by the implementation core.)<br> ++(This is normally done by the implementation core.)<br /> + <code>((test-runner-on-<var>event</var> <var>runner</var>) <var>runner</var> <var>other-args</var> ...)</code></p> + <p> + The following call-back hooks are available.</p> + <p> +-<code>(<b>test-runner-on-test-begin</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-test-begin!</b> <var>runner</var> <var>on-test-begin-function</var>)</code><br> +-<code>(<var>on-test-begin-function</var> <var>runner</var>)</code><br> ++<code>(<b>test-runner-on-test-begin</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-test-begin!</b> <var>runner</var> <var>on-test-begin-function</var>)</code><br /> ++<code>(<var>on-test-begin-function</var> <var>runner</var>)</code><br /> + The <var>on-test-begin-function</var> is called at the start of an + individual testcase, before the test expression (and expected value) are + evaluated. + </p> + <p> +-<code>(<b>test-runner-on-test-end</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-test-end!</b> <var>runner</var> <var>on-test-end-function</var>)</code><br> +-<code>(<var>on-test-end-function</var> <var>runner</var>)</code><br> ++<code>(<b>test-runner-on-test-end</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-test-end!</b> <var>runner</var> <var>on-test-end-function</var>)</code><br /> ++<code>(<var>on-test-end-function</var> <var>runner</var>)</code><br /> + The <var>on-test-end-function</var> is called at the end of an + individual testcase, when the result of the test is available.</p> + <p> +-<code>(<b>test-runner-on-group-begin</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-group-begin!</b> <var>runner</var> <var>on-group-begin-function</var>)</code><br> +-<code>(<var>on-group-begin-function</var> <var>runner</var> <var>suite-name</var> <var>count</var>)</code><br> ++<code>(<b>test-runner-on-group-begin</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-group-begin!</b> <var>runner</var> <var>on-group-begin-function</var>)</code><br /> ++<code>(<var>on-group-begin-function</var> <var>runner</var> <var>suite-name</var> <var>count</var>)</code><br /> + The <var>on-group-begin-function</var> is called by a <code>test-begin</code>, + including at the start of a <code>test-group</code>. + The <var>suite-name</var> is a Scheme string, + and <var>count</var> is an integer or <code>#f</code>.</p> + <p> +-<code>(<b>test-runner-on-group-end</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-group-end!</b> <var>runner</var> <var>on-group-end-function</var>)</code><br> +-<code>(<var>on-group-end-function</var> <var>runner</var>)</code><br> ++<code>(<b>test-runner-on-group-end</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-group-end!</b> <var>runner</var> <var>on-group-end-function</var>)</code><br /> ++<code>(<var>on-group-end-function</var> <var>runner</var>)</code><br /> + The <var>on-group-end-function</var> is called by a <code>test-end</code>, + including at the end of a <code>test-group</code>.</p> + <p> +-<code>(<b>test-runner-on-bad-count</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-bad-count!</b> <var>runner</var> <var>on-bad-count-function</var>)</code><br> +-<code>(<var>on-bad-count-function</var> <var>runner</var> <var>actual-count</var> <var>expected-count</var>)</code><br> ++<code>(<b>test-runner-on-bad-count</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-bad-count!</b> <var>runner</var> <var>on-bad-count-function</var>)</code><br /> ++<code>(<var>on-bad-count-function</var> <var>runner</var> <var>actual-count</var> <var>expected-count</var>)</code><br /> + Called from <code>test-end</code> (before the <var>on-group-end-function</var> + is called) if an <var>expected-count</var> was specified by the matching + <code>test-begin</code> and the <var>expected-count</var> does not match + the <var>actual-count</var> of tests actually executed or skipped.</p> + <p> +-<code>(<b>test-runner-on-base-end-name</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-bad-end-name!</b> <var>runner</var> <var>on-bad-end-name-function</var>)</code><br> +-<code>(<var>on-bad-end-name-function</var> <var>runner</var> <var>begin-name</var> <var>end-name</var>)</code><br> ++<code>(<b>test-runner-on-bad-end-name</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-bad-end-name!</b> <var>runner</var> <var>on-bad-end-name-function</var>)</code><br /> ++<code>(<var>on-bad-end-name-function</var> <var>runner</var> <var>begin-name</var> <var>end-name</var>)</code><br /> + Called from <code>test-end</code> (before the <var>on-group-end-function</var> + is called) if a <var>suite-name</var> was specified, and it did not that the + name in the matching <code>test-begin</code>.</p> + <p> +-<code>(<b>test-runner-on-final</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-on-final!</b> <var>runner</var> <var>on-final-function</var>)</code><br> +-<code>(<var>on-final-function</var> <var>runner</var>)</code><br> ++<code>(<b>test-runner-on-final</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-on-final!</b> <var>runner</var> <var>on-final-function</var>)</code><br /> ++<code>(<var>on-final-function</var> <var>runner</var>)</code><br /> + The <var>on-final-function</var> takes one parameter (a test-runner) + and typically displays a summary (count) of the tests. + The <var>on-final-function</var> is called after called the +@@ -705,73 +740,74 @@ to the standard output port the number of tests of the various kinds. + </p> + <p> + The default test-runner returned by <code>test-runner-simple</code> +-uses the following call-back functions:<br> +-<code>(<b>test-on-test-begin-simple</b> <var>runner</var>)</code><br> +-<code>(<b>test-on-test-end-simple</b> <var>runner</var>)</code><br> +-<code>(<b>test-on-group-begin-simple</b> <var>runner</var> <var>suite-name</var> <var>count</var>)</code><br> +-<code>(<b>test-on-group-end-simple</b> <var>runner</var>)</code><br> +-<code>(<b>test-on-bad-count-simple</b> <var>runner</var> <var>actual-count</var> <var>expected-count</var>)</code><br> +-<code>(<b>test-on-bad-end-name-simple</b> <var>runner</var> <var>begin-name</var> <var>end-name</var>)</code><br> +-You can call those if you want to write a your own test-runner.</p> ++uses the following call-back functions:<br /> ++<code>(<b>test-on-test-begin-simple</b> <var>runner</var>)</code><br /> ++<code>(<b>test-on-test-end-simple</b> <var>runner</var>)</code><br /> ++<code>(<b>test-on-group-begin-simple</b> <var>runner</var> <var>suite-name</var> <var>count</var>)</code><br /> ++<code>(<b>test-on-group-end-simple</b> <var>runner</var>)</code><br /> ++<code>(<b>test-on-bad-count-simple</b> <var>runner</var> <var>actual-count</var> <var>expected-count</var>)</code><br /> ++<code>(<b>test-on-bad-end-name-simple</b> <var>runner</var> <var>begin-name</var> <var>end-name</var>)</code><br /> ++You can call those if you want to write your own test-runner.</p> + +-<h3>Test-runner components</h3> ++<h4>Test-runner components</h4> + <p> + The following functions are for accessing the other components of a test-runner. + They would normally only be used to write a new test-runner or + a match-predicate.</p> + <p> +-<code>(<b>test-runner-pass-count</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-pass-count</b> <var>runner</var>)</code><br /> + Returns the number of tests that passed, and were expected to pass.</p> + <p> +-<code>(<b>test-runner-fail-count</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-fail-count</b> <var>runner</var>)</code><br /> + Returns the number of tests that failed, but were expected to pass.</p> + <p> +-<code>(<b>test-runner-xpass-count</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-xpass-count</b> <var>runner</var>)</code><br /> + Returns the number of tests that passed, but were expected to fail.</p> + <p> +-<code>(<b>test-runner-xfail-count</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-xfail-count</b> <var>runner</var>)</code><br /> + Returns the number of tests that failed, and were expected to pass.</p> + <p> +-<code>(<b>test-runner-skip-count</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-skip-count</b> <var>runner</var>)</code><br /> + Returns the number of tests or test groups that were skipped.</p> + <p> +-<code>(<b>test-runner-test-name</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-test-name</b> <var>runner</var>)</code><br /> + Returns the name of the current test or test group, as a string. + During execution of <code>test-begin</code> this is the name of the + test group; during the execution of an actual test, this is the name + of the test-case. + If no name was specified, the name is the empty string.</p> + <p> +-<code>(<b>test-runner-group-path</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-group-path</b> <var>runner</var>)</code><br /> + A list of names of groups we're nested in, with the outermost group first.</p> + <p> +-<code>(<b>test-runner-group-stack</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-group-stack</b> <var>runner</var>)</code><br /> + A list of names of groups we're nested in, with the outermost group last. + (This is more efficient than <code>test-runner-group-path</code>, + since it doesn't require any copying.)</p> + <p> +-<code>(<b>test-runner-aux-value</b> <var>runner</var>)</code><br> +-<code>(<b>test-runner-aux-value!</b> <var>runner</var> <var>on-test</var>)</code><br> ++<code>(<b>test-runner-aux-value</b> <var>runner</var>)</code><br /> ++<code>(<b>test-runner-aux-value!</b> <var>runner</var> <var>on-test</var>)</code><br /> + Get or set the <code>aux-value</code> field of a test-runner. + This field is not used by this API or the <code>test-runner-simple</code> + test-runner, but may be used by custom test-runners to store extra state.</p> + <p> +-<code>(<b>test-runner-reset</b> <var>runner</var>)</code><br> ++<code>(<b>test-runner-reset</b> <var>runner</var>)</code><br /> + Resets the state of the <var>runner</var> to its initial state. + </p> + +-<h3>Example</h3> ++<h4>Example</h4> + <p>This is an example of a simple custom test-runner. + Loading this program before running a test-suite will install + it as the default test runner.</p> +-<pre>(define (my-simple-runner filename) ++<pre> ++(define (my-simple-runner filename) + (let ((runner (test-runner-null)) + (port (open-output-file filename)) + (num-passed 0) + (num-failed 0)) +- (test-runner-on-test! runner +- (lambda (runner result) +- (case (cdr (assq 'result-kind result)) ++ (test-runner-on-test-end! runner ++ (lambda (runner) ++ (case (test-result-kind runner) + ((pass xpass) (set! num-passed (+ num-passed 1))) + ((fail xfail) (set! num-failed (+ num-failed 1))) + (else #t)))) +@@ -786,31 +822,31 @@ it as the default test runner.</p> + (lambda () (my-simple-runner "/tmp/my-test.log"))) + </pre> + +-<h1>Implementation</h1> ++<h2>Implementation</h2> + <p> + The test implementation uses <code>cond-expand</code> +-(<a href="http://srfi.schemers.org/srfi-0/srfi-0.html">SRFI-0</a>) ++(<a href="https://srfi.schemers.org/srfi-0/srfi-0.html">SRFI-0</a>) + to select different code depending on certain SRFI names (<code>srfi-9</code>, + <code>srfi-34</code>, <code>srfi-35</code>, <code>srfi-39</code>), + or implementations (<code>kawa</code>). + It should otherwise be portable to any R5RS implementation.</p> + +-<p><a href="http://srfi.schemers.org/srfi-64/testing.scm">testing.scm</a></p> ++<p><a href="https://srfi.schemers.org/srfi-64/testing.scm">testing.scm</a></p> + +-<h2>Examples</h2> +-<p>Here is <a href="http://srfi.schemers.org/srfi-64/srfi-25-test.scm"><code>srfi-25-test.scm</code></a>, ++<h3>Examples</h3> ++<p>Here is <a href="https://srfi.schemers.org/srfi-64/srfi-25-test.scm"><code>srfi-25-test.scm</code></a>, + based converted from Jussi Piitulainen's +-<a href="http://srfi.schemers.org/srfi-25/test.scm"><code>test.scm</code></a> +-for <a href="http://srfi.schemers.org/srfi-25/srfi-25.html">SRFI-25</a>.</p> ++<a href="https://srfi.schemers.org/srfi-25/test.scm"><code>test.scm</code></a> ++for <a href="srfi-25.html">SRFI-25</a>.</p> + +-<h2>Test suite</h2> ++<h3>Test suite</h3> + <p> + Of course we need a test suite for the testing framework itself. +-This suite <code><a href="http://srfi.schemers.org/srfi-64/srfi-64-test.scm">srfi-64-test.scm</a></code> ++This suite <code><a href="https://srfi.schemers.org/srfi-64/srfi-64-test.scm">srfi-64-test.scm</a></code> + was contributed by Donovan Kolbly + <a href="mailto:donovan@rscheme.org"><code><donovan@rscheme.org></code></a>.</p> + +-<h1>Copyright</h1> ++<h2>Copyright</h2> + <p> + Copyright (C) Per Bothner (2005, 2006)</p> + <p> +@@ -832,14 +868,14 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p> +-<hr> ++<hr /> + <address>Author: <a href="mailto:per@bothner.com">Per Bothner</a></address> + <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Francisco Solsona</a></address> + <p> + <!-- Created: Sat Sep 4 12:26:07 PDT 2004 --> + <!-- hhmts start --> +-Last modified: Sun Jan 28 13:40:18 MET 2007 ++Last modified: Thu Mar 31 19:49:52 MST 2011 + <!-- hhmts end --> + </p> +- +-</body></html> ++ </body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html +index 7d8fcb3..c3936b9 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-66.html +@@ -1,40 +1,243 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html> +-<body> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> +-<title>SRFI 66: Octet Vectors</title> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-66 ┃ ++┃ Commit: 055bb8ca2201be49afda2862386612f679fe45dc ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 66: Octet Vectors</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> +-<H1>Title</H1> +- +-Octet Vectors +- +-<H1>Authors</H1> +- +-Michael Sperber +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-To +-provide input on this SRFI, please <CODE> +-<A HREF="mailto:srfi-66@srfi.schemers.org">mailto:srfi-66@srfi.schemers.org</A></CODE>. +-See <A HREF="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</A> to subscribe to the list. You can access previous messages via +-<A HREF="http://srfi.schemers.org/srfi-66/mail-archive/maillist.html">the +-archive of the mailing list</A>. +-<P> +-<UL> +- <LI>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-66/srfi-66.html?rev=1.3">2005/03/11</a></LI> +- <LI>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-66/srfi-66.html?rev=1.4">2005/04/18</a></LI> +- <LI>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-66/srfi-66.html?rev=1.5">2005/06/06</a></LI> +- <LI>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-66/srfi-66.html?rev=1.6">2005/12/15</a></LI> +-</UL> +- +-<h1>Abstract</h1><p>This SRFI defines a set of procedures for creating, accessing, and manipulating uniform vectors of octets.</p><h1>Rationale</h1><p>A number of applications deal with sequences of octets (often called bytes), most prominently interfaces to C and I/O. Vectors are typically too space-costly and too slow to work well in these circumstance. This justifies having a separate type for octet vectors.</p><p>This SRFI is related to <a href="http://srfi.schemers.org/srfi-4/">SRFI 4</a> (Homogeneous numeric vector datatypes), which also provides vectors of octets, and uses names consistent with it. However, the extension described here does not require any extensions to the syntax of the underlying Scheme system, and provides a slightly richer set of primtives.</p><p>Scheme systems implementing both SRFI 4 and this SRFI should use the same type for <code>u8vector</code> and octet vectors as specified here.</p><h1>Specification</h1><p>Octet vectors are objects of a new type. This type may or may not be disjoint from the type of regular vectors. Its elements must be octets, that is, exact integers in the range [0,255].</p><p>As with vectors, the length of a octet vector is the number of elements it contains. This number is fixed. A valid index into a octet vector is an exact, non-negative integer. The first element of a octet vector has index 0, the last element has an index one less than the length of the vector.</p><dl><dt><code>(u8vector? </code><var>obj</var><code>)</code></dt><dd><p>Returns <code>#t</code> if <var>obj</var> is a vector, otherwise returns <code>#f</code>. Analogous to <code>vector?</code>.</p></dd><dt><code>(make-u8vector </code><var>k</var> <var>fill</var><code>)</code></dt><dd><p>Returns a newly allocated octet vector of <var>k</var> elements. Each element is initialized to <var>fill</var>. <var>Fill</var> must be an octet. Analogous to <code>make-vector</code>.</p></dd><dt><code>(u8vector </code><var>octet</var> ...<code>)</code></dt><dd><p>Returns a newly allocated octet vector whose elements contain the given arguments, which must all be octets. Analogous to <code>vector</code>.</p></dd><dt><code>(u8vector->list </code><var>u8vector</var><code>)</code></dt><dt><code>(list->u8vector </code><var>octets</var><code>)</code></dt><dd><p><code>u8vector->list</code>returns a newly allocated list of the elements of <var>u8vector</var> in the same order.Analogous to <code>vector->list</code>.</p></dd><dd><p><code>List->u8vector</code> returns a newly allocated octet vector whose elements are the elements of list <var>octets</var>, which must all be octets. Analogous to <code>list->vector</code>.</p></dd><dt><code>(u8vector-length </code><var>u8vector</var><code>)</code></dt><dd><p>Returns the number of elements in <var>u8vector</var> as an exact integer. Analogous to <code>vector-length</code>.</p></dd><dt><code>(u8vector-ref </code><var>u8vector</var> <var>k</var><code>)</code></dt><dd><p><var>k</var> must be a valid index of <var>u8vector</var>. <code>u8vector-ref</code> returns the contents of element <var>k</var> of <var>u8vector</var>. Analogous to <code>vector-ref</code>.</p></dd><dt><code>(u8vector-set! </code><var>u8vector</var> <var>k</var> <var>octet</var><code>)</code></dt><dd><p><var>k</var> must be a valid index of <var>u8vector</var>. <code>u8vector-set!</code> stores <var>octet</var> in element <var>k</var> of <var>u8vector</var>. The number of return values and the return values are unspecified. However, the number of return values is such that it is accepted by a continuation created by <code>begin</code>. Analogous to <code>vector-set!</code>.</p></dd><dt><code>(u8vector=? </code><var>u8vector-1</var> <var>u8vector-2</var><code>)</code></dt><dd><p>Returns <var>#t</var> if <var>u8vector-1</var> and <var>u8vector-2</var> are equal---that is, if they have the same length and equal elements at all valid indices.</p></dd><dt><code>(u8vector-compare </code><var>u8vector-1</var> <var>u8vector-2</var><code>)</code></dt><dd><p>Compares <var>u8vector-1</var> and <var>u8vector-2</var> and returns a value consistent with the vector ordering specified in <a href="http://srfi.schemers.org/srfi-67/">SRFI 67</a>, i.e. -1 if <var>u8vector-1</var> is smaller than <var>u8vector-2</var>, 0 if they are equal, and 1 if <var>u8vector-1</var> is greater than <var>u8vector-2</var>. Shorter vectors are always smaller than longer ones, and vectors of equal length are compared lexicographically.</p></dd><dt><code>(u8vector-copy! </code><var>source</var> <var>source-start</var> <var>target</var> <var>target-start</var> <var>n</var><code>)</code></dt><dd><p>Copies data from octet vector <var>source</var> to octet vector <var>target</var>. <var>Source-start</var>, <var>target-start</var>, and <var>n</var> must be non-negative exact integers that satisfy</p><p>0 <= <var>source-start</var> <= <var>source-start</var> + <var>n</var> <= <code>(u8vector-length <var>source</var>)</code></p><p>0 <= <var>target-start</var> <= <var>target-start</var> + <var>n</var> <= <code>(u8vector-length <var>target</var>)</code></p><p>This copies the octets from <var>source</var> at indices [<var>source-start</var>, <var>source-start</var> + <var>n</var>) to consecutive indices in <var>target</var> starting at <var>target-index</var>.</p><p>This must work even if the memory regions for the source and the target overlap, i.e., the octets at the target location after the copy must be equal to the octets at the source location before the copy.</p><p>The number of return values and the return values are unspecified. However, the number of return values is such that it is accepted by a continuation created by <code>begin</code>. Analogous to <code>vector-ref</code>.</p></dd><dt><code>(u8vector-copy </code><var>u8vector</var><code>)</code></dt><dd><p>Returns a newly allocated copy of octet vector <var>u8vector</var>.</p></dd></dl><h1>Reference Implementation</h1><p>This reference implementation makes use of <a href="http://srfi.schemers.org/srfi-9/">SRFI 9</a> (Defining Record Types) and <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> (Error reporting mechanism) .</p><pre>(define-record-type :u8vector ++<h1>SRFI 66: Octet Vectors</h1> ++ ++<p>by Michael Sperber</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 66 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-66/srfi-66.html">https://srfi.schemers.org/srfi-66/srfi-66.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p> ++ This SRFI is currently in <em>final</em> status. Here ++ is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> ++ of each status that a SRFI can hold. To provide input on this SRFI, please ++ send email ++ to <code><a href="mailto:srfi+minus+66+at+srfi+dotschemers+dot+org">srfi-66@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. ++ To subscribe to the list, ++ follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these ++ instructions</a>. You can access previous messages via the mailing ++ list <a href="https://srfi-email.schemers.org/srfi-66">archive</a>.</p> ++<ul> ++ <li> ++ Received: <a href="https://srfi.schemers.org/srfi-66/srfi-66-1.3.html">2005-03-11</a> ++ </li> ++ <li> ++ Revised: <a href="https://srfi.schemers.org/srfi-66/srfi-66-1.4.html">2005-04-18</a> ++ </li> ++ <li> ++ Revised: <a href="https://srfi.schemers.org/srfi-66/srfi-66-1.5.html">2005-06-06</a> ++ </li> ++ <li> ++ Final: <a href="https://srfi.schemers.org/srfi-66/srfi-66-1.6.html">2005-12-15</a> ++ </li> ++ <li> ++ Revised to fix errata: ++ <ul> ++ <li> ++ 2017-07-17 (Added missing arguments to <code>u8vector-ref</code>.) ++ </li> ++ </ul> ++ </li> ++</ul> ++ ++<h2>Abstract</h2> ++<p> ++ This SRFI defines a set of procedures for creating, accessing, and ++ manipulating uniform vectors of octets. ++</p> ++<h2>Rationale</h2> ++<p> ++ A number of applications deal with sequences of octets (often called bytes), ++ most prominently interfaces to C and I/O. Vectors are typically too ++ space-costly and too slow to work well in these circumstance. This ++ justifies having a separate type for octet vectors. ++</p> ++<p> ++ This SRFI is related to <a href="srfi-4.html">SRFI ++ 4</a> (Homogeneous numeric vector datatypes), which also provides vectors of ++ octets, and uses names consistent with it. However, the extension described ++ here does not require any extensions to the syntax of the underlying Scheme ++ system, and provides a slightly richer set of primtives. ++</p> ++<p> ++ Scheme systems implementing both SRFI 4 and this SRFI should use the same ++ type for <code>u8vector</code> and octet vectors as specified here. ++</p> ++<h2>Specification</h2> ++<p> ++ Octet vectors are objects of a new type. This type may or may not be ++ disjoint from the type of regular vectors. Its elements must be octets, ++ that is, exact integers in the range [0,255]. ++</p> ++<p> ++ As with vectors, the length of a octet vector is the number of elements it ++ contains. This number is fixed. A valid index into a octet vector is an ++ exact, non-negative integer. The first element of a octet vector has index ++ 0, the last element has an index one less than the length of the vector. ++</p> ++<dl> ++<dt><code>(u8vector? </code><var>obj</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns <code>#t</code> if <var>obj</var> is an octect vector, otherwise ++ returns <code>#f</code>. Analogous to <code>vector?</code>. ++ </p> ++</dd> ++<dt><code>(make-u8vector </code><var>k</var> <var>fill</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns a newly allocated octet vector of <var>k</var> elements. Each ++ element is initialized to <var>fill</var>. <var>Fill</var> must be an ++ octet. Analogous to <code>make-vector</code>. ++ </p> ++</dd> ++<dt><code>(u8vector </code><var>octet</var> ...<code>)</code></dt> ++<dd> ++ <p> ++ Returns a newly allocated octet vector whose elements contain the given ++ arguments, which must all be octets. Analogous to <code>vector</code>. ++ </p> ++</dd> ++<dt><code>(u8vector->list </code><var>u8vector</var><code>)</code></dt> ++<dt><code>(list->u8vector </code><var>octets</var><code>)</code></dt> ++<dd> ++ <p> ++ <code>u8vector->list</code>returns a newly allocated list of the ++ elements of <var>u8vector</var> in the same order.Analogous ++ to <code>vector->list</code>. ++ </p> ++</dd> ++<dd> ++ <p> ++ <code>List->u8vector</code> returns a newly allocated octet vector ++ whose elements are the elements of list <var>octets</var>, which must all ++ be octets. Analogous to <code>list->vector</code>. ++ </p> ++</dd> ++<dt><code>(u8vector-length </code><var>u8vector</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns the number of elements in <var>u8vector</var> as an exact integer. ++ Analogous to <code>vector-length</code>. ++ </p> ++</dd> ++<dt><code>(u8vector-ref </code><var>u8vector</var> <var>k</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>k</var> must be a valid index ++ of <var>u8vector</var>. <code>u8vector-ref</code> returns the contents of ++ element <var>k</var> of <var>u8vector</var>. Analogous ++ to <code>vector-ref</code>. ++ </p> ++</dd> ++<dt><code>(u8vector-set! </code><var>u8vector</var> <var>k</var> <var>octet</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>k</var> must be a valid index ++ of <var>u8vector</var>. <code>u8vector-set!</code> ++ stores <var>octet</var> in element <var>k</var> of <var>u8vector</var>. ++ The number of return values and the return values are unspecified. ++ However, the number of return values is such that it is accepted by a ++ continuation created by <code>begin</code>. Analogous ++ to <code>vector-set!</code>. ++ </p> ++</dd> ++<dt><code>(u8vector=? </code><var>u8vector-1</var> <var>u8vector-2</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns <var>#t</var> if <var>u8vector-1</var> and <var>u8vector-2</var> ++ are equal---that is, if they have the same length and equal elements at ++ all valid indices. ++ </p> ++</dd> ++<dt><code>(u8vector-compare </code><var>u8vector-1</var> <var>u8vector-2</var><code>)</code></dt> ++<dd> ++ <p> ++ Compares <var>u8vector-1</var> and <var>u8vector-2</var> and returns a ++ value consistent with the vector ordering specified ++ in <a href="https://srfi.schemers.org/srfi-67/">SRFI 67</a>, i.e. -1 ++ if <var>u8vector-1</var> is smaller than <var>u8vector-2</var>, 0 if they ++ are equal, and 1 if <var>u8vector-1</var> is greater ++ than <var>u8vector-2</var>. Shorter vectors are always smaller than longer ++ ones, and vectors of equal length are compared lexicographically. ++ </p> ++</dd> ++<dt><code>(u8vector-copy! </code><var>source</var> <var>source-start</var> <var>target</var> <var>target-start</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ Copies data from octet vector <var>source</var> to octet ++ vector <var>target</var>. <var>Source-start</var>, <var>target-start</var>, ++ and <var>n</var> must be non-negative exact integers that satisfy ++ </p> ++ <p> ++ 0 <= <var>source-start</var> <= <var>source-start</var> ++ + <var>n</var> <= <code>(u8vector-length <var>source</var>)</code> ++ </p> ++ <p> ++ 0 <= <var>target-start</var> <= <var>target-start</var> ++ + <var>n</var> <= <code>(u8vector-length <var>target</var>)</code> ++ </p> ++ <p> ++ This copies the octets from <var>source</var> at indices ++ [<var>source-start</var>, <var>source-start</var> + <var>n</var>) to ++ consecutive indices in <var>target</var> starting ++ at <var>target-index</var>. ++ </p> ++ <p> ++ This must work even if the memory regions for the source and the target ++ overlap, i.e., the octets at the target location after the copy must be ++ equal to the octets at the source location before the copy. ++ </p> ++ <p> ++ The number of return values and the return values are unspecified. ++ However, the number of return values is such that it is accepted by a ++ continuation created by <code>begin</code>. Analogous ++ to <code>vector-ref</code>. ++ </p> ++</dd> ++<dt><code>(u8vector-copy </code><var>u8vector</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns a newly allocated copy of octet vector <var>u8vector</var>. ++ </p> ++</dd> ++</dl> ++<h2>Reference Implementation</h2> ++<p> ++ This reference implementation makes use ++ of <a href="srfi-9.html">SRFI 9</a> (Defining Record ++ Types) and <a href="srfi-23.html">SRFI 23</a> (Error ++ reporting mechanism) . ++</p> ++<pre>(define-record-type :u8vector + (really-make-u8vector elements) + u8vector? + (elements u8vector-elements)) +@@ -44,7 +247,7 @@ archive of the mailing list</A>. + (exact? thing) + (>= thing 0) + (<= thing 255))) +- (error "not a octet" thing))) ++ (error "not a octet" thing))) + + (define (make-u8vector k fill) + (ensure-octet fill) +@@ -94,8 +297,8 @@ archive of the mailing list</A>. + (and (= size (u8vector-length u8vector-2)) + (let loop ((i 0)) + (or (>= i size) +- (and (= (u8vector-ref u8vector-1) +- (u8vector-ref u8vector-2)) ++ (and (= (u8vector-ref u8vector-1 i) ++ (u8vector-ref u8vector-2 i)) + (loop (+ 1 i)))))))) + + (define (u8vector-compare u8vector-1 u8vector-2) +@@ -113,27 +316,45 @@ archive of the mailing list</A>. + (cond ((< elt-1 elt-2) -1) + ((> elt-1 elt-2) 1) + (else (loop (+ i 1))))))))))) +-</pre><h1>References</h1><ul><li><a href="http://srfi.schemers.org/srfi-4/">SRFI 4</a> (Homogeneous numeric vector datatypes)</li><li>The "Byte Vectors" section of <i>The Incomplete Scheme 48 Reference Manual</i> available from <a href="http://www.s48.org/">this page</a>.</li></ul></body><H1>Copyright</H1> +-Copyright (C) Michael Sperber (2005). All Rights Reserved. ++</pre> ++<h2>References</h2> ++<ul> ++ <li> ++ <a href="srfi-4.html">SRFI 4</a> (Homogeneous ++ numeric vector datatypes) ++ </li> ++ <li> ++ The "Byte Vectors" section of <i>The Incomplete Scheme 48 ++ Reference Manual</i> available from <a href="http://www.s48.org/">this ++ page</a>. ++ </li> ++</ul> ++<h2>Copyright</h2> ++<p> ++ Copyright (C) Michael Sperber (2005). All Rights Reserved. ++</p> + <p> +-Permission is hereby granted, free of charge, to any person obtaining a +-copy of this software and associated documentation files (the "Software"), +-to deal in the Software without restriction, including without limitation +-the rights to use, copy, modify, merge, publish, distribute, sublicense, +-and/or sell copies of the Software, and to permit persons to whom the +-Software is furnished to do so, subject to the following conditions: ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to ++ deal in the Software without restriction, including without limitation the ++ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ sell copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++</p> + <p> +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++</p> + <p> +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +-DEALINGS IN THE SOFTWARE. +- +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">David Van Horn</a></address> +-</body></html> ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ IN THE SOFTWARE. ++</p> ++<hr /> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> ++</body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html +index 6e4c3bb..3f99b11 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-69.html +@@ -1,69 +1,81 @@ +-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en"> + <head> +- <title>SRFI 69: Basic hash tables</title> +- <meta name="author" content="Panu Kalliokoski"> +- <meta name="generator" content="stx2any"> +- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +- <meta name="date" content="2005-02-24"> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-69 ┃ ++┃ Commit: 750d0883f1ead0dfe186b6465de7e4f43815f51c ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 69: Basic hash tables</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ <meta content="Panu Kalliokoski" name="author" /> ++ <meta content="stx2any" name="generator" /> ++ <meta content="2005-02-24" name="date" /> + </head> + <body> + +-<a name="Ttl"><H1>Title</H1></a> ++<h1>SRFI 69: Basic hash tables</h1> + +-SRFI 69: Basic hash tables ++<p>by Panu Kalliokoski</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 69 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-69/srfi-69.html">https://srfi.schemers.org/srfi-69/srfi-69.html</a>.</p></blockquote></blockquote></blockquote> + +-<a name="thr"><H1>Author</H1></a> ++<h2>Status</h2> + +-Panu Kalliokoski +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a HREF="http://srfi.schemers.org/srfi-process.html">here</a>. +-It will remain in draft status until 2005/09/09, or as amended. To +-provide input on this SRFI, please <code> +-<a HREF="mailto:srfi-69@srfi.schemers.org">mailto:srfi-69@srfi.schemers.org</a></code>. +-See <a HREF="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access previous messages via +-<a HREF="http://srfi.schemers.org/srfi-69/mail-archive/maillist.html">the +-archive of the mailing list</a>. +-<p> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+69%20%20+at+srfi+dotschemers+dot+org">srfi-69 @<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-69">archive</a>.</p> + <ul> +- <li>Received: 2005/04/25</li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-69/srfi-69.html?rev=1.1">2005/05/09</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-69/srfi-69.html?rev=1.2">2005/08/03</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-69/srfi-69.html?rev=1.3">2005/08/10</a></li> +- <li>Draft extended: 2005/08/10 - 2005/09/09</li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-69/srfi-69.html?rev=1.4">2005/08/30</a></li> +- <li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-69/srfi-69.html?rev=1.5">2005/09/14</a></li> ++ <li>Received: 2005-04-25</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-69/srfi-69-1.1.html">2005-05-09</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-69/srfi-69-1.2.html">2005-08-03</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-69/srfi-69-1.3.html">2005-08-10</a></li> ++ <li>Draft extended: 2005-08-10--2005-09-09</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-69/srfi-69-1.4.html">2005-08-30</a></li> ++ <li>Final: <a href="https://srfi.schemers.org/srfi-69/srfi-69-1.5.html">2005-09-14</a></li> + </ul> + +-<h1><a name="bstr">Abstract</a></h1> ++<h2 id="bstr">Abstract</h2> + + <p>This SRFI defines basic hash tables. Hash tables are widely recognised + as a fundamental data structure for a wide variety of applications. A + hash table is a data structure that: +- ++</p> + <ol><li>provides a mapping from some set of keys to some set of values + associated to those keys +-<li>has no intrinsic order for the (key, value) associations it contains +-<li>supports in-place modification as the primary means of setting the ++</li><li>has no intrinsic order for the (key, value) associations it contains ++</li><li>supports in-place modification as the primary means of setting the + contents of a hash table +-<li>provides key lookup and destructive update in amortised constant ++</li><li>provides key lookup and destructive update in amortised constant + time, provided that a good hash function is used. + +-</ol><p>This SRFI aims to accomplish these goals: +- ++</li></ol> ++<p>This SRFI aims to accomplish these goals: ++</p> + <ol><li>to provide a consistent, generic and widely applicable API for hash + tables +-<li>to improve code portability by providing a standard hash table ++</li><li>to improve code portability by providing a standard hash table + facility with guaranteed behaviour +-<li>to help the programmer by defining utility routines that account for ++</li><li>to help the programmer by defining utility routines that account for + the most common situations of using hash tables. + +-</ol><h1><a name="sss">Issues</a></h1> ++</li></ol> ++ ++<h2 id="sss">Issues</h2> + + <p>There is no single best way to make hash tables. The tables presented + in this SRFI aim at being both conceptually simple and usable for a wide +@@ -77,7 +89,7 @@ the global environment, and specifically, to provide support for + between implementation-specific environment data types and the hash + table API presented here; however, these issues are left open. + +-<p>This SRFI does not conform to the interface of maps presented in SRFI ++</p><p>This SRFI does not conform to the interface of maps presented in SRFI + 44. Following SRFI 44 would seriously cripple the interface of hash + tables. The naming of the operations for maps in SRFI 44 goes against + common use and is unnatural. However, this SRFI has been written so +@@ -85,15 +97,16 @@ that it does not <em>prevent</em> a SRFI-44 API to hash tables. An + implementation supporting both SRFI 44 and this SRFI is encouraged to + provide a SRFI 44 interface to hash tables in addition to the one + presented here. ++</p> + +-<h1><a name="Rtn">Rationale</a></h1> ++<h2 id="Rtn">Rationale</h2> + + <p>Hash tables are widely recognised as a fundamental data structure for + many kinds of computational tasks. Thus far, there is no existing + standard for Scheme hash tables; however, almost every non-minimal + Scheme implementation provides some kind of hash table functionality. + +-<p>Alas, although somewhat similar, these hash table APIs have many ++</p><p>Alas, although somewhat similar, these hash table APIs have many + differences: some trivial, like the naming of certain functions; some + complex, like revealing different aspects of the internal implementation + to the user; some coarse, like requiring keys to be of some specific +@@ -102,86 +115,89 @@ hash table in advance to get optimal performance. As a result, the + existing hash table facilities cannot be used to write portable + programs. + +-<p>The primary aim of this SRFI is to establish a standard API for hash ++</p><p>The primary aim of this SRFI is to establish a standard API for hash + tables so that portable programs can be written that make efficient use + of common hash table functionality. The SRFI resolves discrepancies + that exist between the various hash table API's with respect to naming + and semantics of hash table operations. A lot of effort has been put +-into making the API consistent, simple and generic. The SRFI also ++into making the the API consistent, simple and generic. The SRFI also + defines some of the most common utility routines that would otherwise + need to be written and rewritten for various applications. + +-<p>Incorporating this SRFI as a standard feature in Scheme implementations ++</p><p>Incorporating this SRFI as a standard feature in Scheme implementations + makes it possible to write efficient and portable programs that use hash + tables. ++</p> + +-<h1><a name="Spcf">Specification</a></h1> ++<h2 id="Spcf">Specification</h2> + + <p>Names defined in this SRFI: +- ++</p> + <dl><dt>Type constructors and predicate</dt> +-<dd><a href="srfi-69.html#mkh">make-hash-table</a>, <a href="srfi-69.html#hsht">hash-table?</a>, <a href="srfi-69.html#lst">alist->hash-table</a> ++<dd><a href="#mkh">make-hash-table</a>, <a href="#hsht">hash-table?</a>, <a href="#lst">alist->hash-table</a> + + </dd><dt>Reflective queries</dt> +-<dd><a href="srfi-69.html#hsht1">hash-table-equivalence-function</a>, <a href="srfi-69.html#hsht2">hash-table-hash-function</a> ++<dd><a href="#hsht1">hash-table-equivalence-function</a>, <a href="#hsht2">hash-table-hash-function</a> + + </dd><dt>Dealing with single elements</dt> +-<dd><a href="srfi-69.html#hsht3">hash-table-ref</a>, <a href="srfi-69.html#hsht4">hash-table-ref/default</a>, <a href="srfi-69.html#hsht5">hash-table-set!</a>, +-<a href="srfi-69.html#hsht6">hash-table-delete!</a>, <a href="srfi-69.html#hsht7">hash-table-exists?</a>, +-<a href="srfi-69.html#hsht8">hash-table-update!</a>, <a href="srfi-69.html#hsht9">hash-table-update!/default</a> ++<dd><a href="#hsht3">hash-table-ref</a>, <a href="#hsht4">hash-table-ref/default</a>, <a href="#hsht5">hash-table-set!</a>, ++<a href="#hsht6">hash-table-delete!</a>, <a href="#hsht7">hash-table-exists?</a>, ++<a href="#hsht8">hash-table-update!</a>, <a href="#hsht9">hash-table-update!/default</a> + + </dd><dt>Dealing with the whole contents</dt> +-<dd><a href="srfi-69.html#hsht11">hash-table-size</a>, <a href="srfi-69.html#hsht12">hash-table-keys</a>, <a href="srfi-69.html#hsht13">hash-table-values</a>, +-<a href="srfi-69.html#hsht14">hash-table-walk</a>, <a href="srfi-69.html#hsht15">hash-table-fold</a>, <a href="srfi-69.html#hsht16">hash-table->alist</a>, +-<a href="srfi-69.html#hsht17">hash-table-copy</a>, <a href="srfi-69.html#hsht18">hash-table-merge!</a> ++<dd><a href="#hsht11">hash-table-size</a>, <a href="#hsht12">hash-table-keys</a>, <a href="#hsht13">hash-table-values</a>, ++<a href="#hsht14">hash-table-walk</a>, <a href="#hsht15">hash-table-fold</a>, <a href="#hsht16">hash-table->alist</a>, ++<a href="#hsht17">hash-table-copy</a>, <a href="#hsht18">hash-table-merge!</a> + + </dd><dt>Hashing</dt> +-<dd><a href="srfi-69.html#hsh">hash</a>, <a href="srfi-69.html#strng">string-hash</a>, <a href="srfi-69.html#strng19">string-ci-hash</a>, <a href="srfi-69.html#hshb">hash-by-identity</a> ++<dd><a href="#hsh">hash</a>, <a href="#strng">string-hash</a>, <a href="#strng19">string-ci-hash</a>, <a href="#hshb">hash-by-identity</a> + +-</dd></dl><p>An implementation that does not provide <tt>hash-table-ref</tt>, ++</dd></dl> ++<p>An implementation that does not provide <tt>hash-table-ref</tt>, + <tt>hash-table-set!</tt>, <tt>hash-table-delete!</tt>, <tt>hash-table-update!</tt>, + <tt>hash-table-exists?</tt>, and <tt>hash-table-size</tt> in amortised constant + time (when a good hash function is used), or fails to provide good hash + function definitions for <tt>hash</tt>, <tt>string-hash</tt>, <tt>string-ci-hash</tt>, + and <tt>hash-by-identity</tt>, does not conform to this SRFI. + +-<p>Hash table implementations are allowed to rely on the fact that the hash ++</p><p>Hash table implementations are allowed to rely on the fact that the hash + value of a key in hash table does not change. In most cases, modifying + a key in-place after it has been inserted into the hash table will + violate this constraint and thus leads to unspecified behaviour. ++</p> + +-<h2><a name="Tpc">Type constructors and predicate</a></h2> +- +-<p>Procedure: <a name="mkh">make-hash-table</a> [ <var>equal?</var> [ <var>hash</var> [ <var>args</var> … ]]] +-→ <var>hash-table</var> ++<h2 id="Tpc">Type constructors and predicate</h2> + ++<p>Procedure: <a name="mkh">make-hash-table</a> [ <var>equal?</var> [ <var>hash</var> [ <var>args</var> … ]]] ++→ <var>hash-table</var> ++</p> + <p>Create a new hash table with no associations. <var>equal?</var> is a + predicate that should accept two keys and return a boolean telling + whether they denote the same key value; it defaults to <tt>equal?</tt>. +- ++</p> + <p><var>hash</var> is a hash function, and defaults to an appropriate hash function +-for the given <var>equal?</var> predicate (see section <a href="srfi-69.html#Hshn">Hashing</a>). However, ++for the given <var>equal?</var> predicate (see section <a href="#Hshn">Hashing</a>). However, + an acceptable default is not guaranteed to be given for any equivalence + predicate coarser than <tt>equal?</tt>, except for <tt>string-ci=?</tt>.<small>[1]</small> The function <var>hash</var> must be acceptable for <var>equal?</var>, so if + you use coarser equivalence than <tt>equal?</tt> other than <tt>string-ci=?</tt>, + you must always provide the function <var>hash</var> yourself. +-<br><small>[1]</small> An ++<br /><small>[1]</small> An + equivalence predicate <var>c1</var> is coarser than a equivalence predicate <var>c2</var> + iff there exist values <var>x</var> and <var>y</var> such that <tt>(and (c1 x y) (not (c2 x +-y)))</tt>.<br> +- ++y)))</tt>. ++</p> + <p>Implementations are allowed to use the rest <var>args</var> for + implementation-specific extensions. Be warned, though, that using these + extensions will make your program less portable. +- +-<p>Procedure: <a name="hsht">hash-table?</a> <var>obj</var> → <var>boolean</var> +- ++</p> ++<p>Procedure: <a name="hsht">hash-table?</a> <var>obj</var> → <var>boolean</var> ++</p> + <p>A predicate to test whether a given object <var>obj</var> is a hash table. The + hash table type should be disjoint from all other types, if possible. +- +-<p>Procedure: <a name="lst">alist->hash-table</a> <var>alist</var> [ <var>equal?</var> [ <var>hash</var> +-[ <var>args</var> … ]]] → <var>hash-table</var> +- ++</p> ++<p>Procedure: <a name="lst">alist->hash-table</a> <var>alist</var> [ <var>equal?</var> [ <var>hash</var> ++[ <var>args</var> … ]]] → <var>hash-table</var> ++</p> + <p>Takes an <q>association list</q> <var>alist</var> and creates a hash table + <var>hash-table</var> which maps the <tt>car</tt> of every element in <var>alist</var> to the + <tt>cdr</tt> of corresponding elements in <var>alist</var>. <var>equal?</var>, <var>hash</var>, and +@@ -191,24 +207,26 @@ precedence over later ones. (Note: the choice of using <tt>cdr</tt> (instead + of <tt>cadr</tt>) for values tries to strike balance between the two + approaches: using <tt>cadr</tt> would render this procedure unusable for + <tt>cdr</tt> alists, but not vice versa.) +- +-<p>The rest <var>args</var> are passed to <a href="srfi-69.html#mkh">make-hash-table</a> and can thus be used for ++</p> ++<p>The rest <var>args</var> are passed to <a href="#mkh">make-hash-table</a> and can thus be used for + implementation-specific extensions. ++</p> + +-<h2><a name="Rflc">Reflective queries</a></h2> ++<h2 id="Rflc">Reflective queries</h2> + + <p>Procedure: <a name="hsht1">hash-table-equivalence-function</a> <var>hash-table</var> +- ++</p> + <p>Returns the equivalence predicate used for keys of <var>hash-table</var>. +- ++</p> + <p>Procedure: <a name="hsht2">hash-table-hash-function</a> <var>hash-table</var> +- ++</p> + <p>Returns the hash function used for keys of <var>hash-table</var>. ++</p> + +-<h2><a name="Dln">Dealing with single elements</a></h2> +- +-<p>Procedure: <a name="hsht3">hash-table-ref</a> <var>hash-table</var> <var>key</var> [ <var>thunk</var> ] → <var>value</var> ++<h2 id="Dln">Dealing with single elements</h2> + ++<p>Procedure: <a name="hsht3">hash-table-ref</a> <var>hash-table</var> <var>key</var> [ <var>thunk</var> ] → <var>value</var> ++</p> + <p>This procedure returns the <var>value</var> associated to <var>key</var> in <var>hash-table</var>. + If no <var>value</var> is associated to <var>key</var> and <var>thunk</var> is given, it is called + with no arguments and its value is returned; if <var>thunk</var> is not given, an +@@ -217,28 +235,28 @@ Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + <var>hash-table</var>. (Note: this rules out implementation by association lists + or fixed-length hash tables.) +- +-<p>Procedure: <a name="hsht4">hash-table-ref/default</a> <var>hash-table</var> <var>key</var> <var>default</var> → ++</p> ++<p>Procedure: <a name="hsht4">hash-table-ref/default</a> <var>hash-table</var> <var>key</var> <var>default</var> → + <var>value</var> +- ++</p> + <p>Evaluates to the same value as <tt>(hash-table-ref hash-table key (lambda + () default))</tt>. + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + <var>hash-table</var>. (Note: this rules out implementation by association lists + or fixed-length hash tables.) +- +-<p>Procedure: <a name="hsht5">hash-table-set!</a> <var>hash-table</var> <var>key</var> <var>value</var> → undefined +- ++</p> ++<p>Procedure: <a name="hsht5">hash-table-set!</a> <var>hash-table</var> <var>key</var> <var>value</var> → undefined ++</p> + <p>This procedure sets the <var>value</var> associated to <var>key</var> in <var>hash-table</var>. + The previous association (if any) is removed. + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + <var>hash-table</var>. (Note: this rules out implementation by association lists + or fixed-length hash tables.) +- +-<p>Procedure: <a name="hsht6">hash-table-delete!</a> <var>hash-table</var> <var>key</var> → undefined +- ++</p> ++<p>Procedure: <a name="hsht6">hash-table-delete!</a> <var>hash-table</var> <var>key</var> → undefined ++</p> + <p>This procedure removes any association to <var>key</var> in <var>hash-table</var>. It is + not an error if no association for that key exists; in this case, + nothing is done. +@@ -246,69 +264,70 @@ Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + <var>hash-table</var>. (Note: this rules out implementation by association lists + or fixed-length hash tables.) +- +-<p>Procedure: <a name="hsht7">hash-table-exists?</a> <var>hash-table</var> <var>key</var> → <var>boolean</var> +- ++</p> ++<p>Procedure: <a name="hsht7">hash-table-exists?</a> <var>hash-table</var> <var>key</var> → <var>boolean</var> ++</p> + <p>This predicate tells whether there is any association to <var>key</var> in + <var>hash-table</var>. + Given a good hash function, this operation should have an (amortised) + complexity of O(1) with respect to the number of associations in + <var>hash-table</var>. (Note: this rules out implementation by association lists + or fixed-length hash tables.) +- ++</p> + <p>Procedure: <a name="hsht8">hash-table-update!</a> <var>hash-table</var> <var>key</var> <var>function</var> +-[ <var>thunk</var> ] → undefined +- ++[ <var>thunk</var> ] → undefined ++</p> + <p>Semantically equivalent to, but may be implemented more efficiently + than, the following code: ++</p> + <pre> + (hash-table-set! hash-table key + (function (hash-table-ref hash-table key thunk))) + </pre> +- + <p>Procedure: <a name="hsht9">hash-table-update!/default</a> +-<var>hash-table</var> <var>key</var> <var>function</var> <var>default</var> → undefined +- ++<var>hash-table</var> <var>key</var> <var>function</var> <var>default</var> → undefined ++</p> + <p>Behaves as if it evaluates to <tt>(hash-table-update! hash-table key + function (lambda () default))</tt>. ++</p> + +-<h2><a name="Dln10">Dealing with the whole contents</a></h2> +- +-<p>Procedure: <a name="hsht11">hash-table-size</a> <var>hash-table</var> → <var>integer</var> ++<h2 id="Dln10">Dealing with the whole contents</h2> + ++<p>Procedure: <a name="hsht11">hash-table-size</a> <var>hash-table</var> → <var>integer</var> ++</p> + <p>Returns the number of associations in <var>hash-table</var>. This operation + must have a complexity of O(1) with respect to the number of + associations in <var>hash-table</var>. +- +-<p>Procedure: <a name="hsht12">hash-table-keys</a> <var>hash-table</var> → <var>list</var> +- ++</p> ++<p>Procedure: <a name="hsht12">hash-table-keys</a> <var>hash-table</var> → <var>list</var> ++</p> + <p>Returns a list of keys in <var>hash-table</var>. The order of the keys is + unspecified. +- +-<p>Procedure: <a name="hsht13">hash-table-values</a> <var>hash-table</var> → <var>list</var> +- ++</p> ++<p>Procedure: <a name="hsht13">hash-table-values</a> <var>hash-table</var> → <var>list</var> ++</p> + <p>Returns a list of values in <var>hash-table</var>. The order of the values is + unspecified, and is not guaranteed to match the order of keys in the +-result of <a href="srfi-69.html#hsht12">hash-table-keys</a>. +- +-<p>Procedure: <a name="hsht14">hash-table-walk</a> <var>hash-table</var> <var>proc</var> → unspecified +- ++result of <a href="#hsht12">hash-table-keys</a>. ++</p> ++<p>Procedure: <a name="hsht14">hash-table-walk</a> <var>hash-table</var> <var>proc</var> → unspecified ++</p> + <p><var>proc</var> should be a function taking two arguments, a <var>key</var> and a <var>value</var>. + This procedure calls <var>proc</var> for each association in <var>hash-table</var>, giving + the key of the association as <var>key</var> and the value of the association as + <var>value</var>. The results of <var>proc</var> are discarded. The order in which + <var>proc</var> is called for the different associations is unspecified. +- ++</p> + <p>(Note: in some implementations, there is a procedure called + <tt>hash-table-map</tt> which does the same as this procedure. However, in + other implementations, <tt>hash-table-map</tt> does something else. In no + implementation that I know of, <tt>hash-table-map</tt> does a real functorial + map that lifts an ordinary function to the domain of hash tables. + Because of these reasons, <tt>hash-table-map</tt> is left outside this SRFI.) +- ++</p> + <p>Procedure: <a name="hsht15">hash-table-fold</a> <var>hash-table</var> <var>f</var> <var>init-value</var> +-→ <var>final-value</var> +- ++→ <var>final-value</var> ++</p> + <p>This procedure calls <var>f</var> for every association in <var>hash-table</var> with + three arguments: the key of the association <var>key</var>, the value of the + association <var>value</var>, and an <q>accumulated value</q>, <var>val</var>. <var>val</var> is +@@ -317,42 +336,44 @@ invocations of <var>f</var>, the return value of the previous invocation of <var + The value <var>final-value</var> returned by <tt>hash-table-fold</tt> is the return + value of the last invocation of <var>f</var>. The order in which <var>f</var> is called + for different associations is unspecified. +- +-<p>Procedure: <a name="hsht16">hash-table->alist</a> <var>hash-table</var> → <var>alist</var> +- ++</p> ++<p>Procedure: <a name="hsht16">hash-table->alist</a> <var>hash-table</var> → <var>alist</var> ++</p> + <p>Returns an association list such that the <tt>car</tt> of each element in + <var>alist</var> is a key in <var>hash-table</var> and the corresponding <tt>cdr</tt> of each + element in <var>alist</var> is the value associated to the key in <var>hash-table</var>. + The order of the elements is unspecified. +- ++</p> + <p>The following should always produce a hash table with the same mappings + as a hash table <tt>h</tt>: ++</p> + <pre> + (alist->hash-table (hash-table->alist h) + (hash-table-equivalence-function h) + (hash-table-hash-function h)) + </pre> + +-<p>Procedure: <a name="hsht17">hash-table-copy</a> <var>hash-table</var> → <var>hash-table</var> +- ++<p>Procedure: <a name="hsht17">hash-table-copy</a> <var>hash-table</var> → <var>hash-table</var> ++</p> + <p>Returns a new hash table with the same equivalence predicate, hash + function and mappings as in <var>hash-table</var>. +- +-<p>Procedure: <a name="hsht18">hash-table-merge!</a> <var>hash-table1</var> <var>hash-table2</var> → ++</p> ++<p>Procedure: <a name="hsht18">hash-table-merge!</a> <var>hash-table1</var> <var>hash-table2</var> → + <var>hash-table</var> +- ++</p> + <p>Adds all mappings in <var>hash-table2</var> into <var>hash-table1</var> and returns the + resulting hash table. This function may modify <var>hash-table1</var> + destructively. ++</p> + +-<h2><a name="Hshn">Hashing</a></h2> ++<h2 id="Hshn">Hashing</h2> + + <p>Hashing means the act of taking some value and producing a number from + the value. A hash function is a function that does this. Every + equivalence predicate <var>e</var> has a set of <var>acceptable</var> hash functions for +-that predicate; a hash function <var>hash</var> is acceptable iff <tt>(e obj1 +-obj2)</tt> → <tt>(= (hash obj1) (hash obj2))</tt>. +- ++that predicate; a hash funtion <var>hash</var> is acceptable iff <tt>(e obj1 ++obj2)</tt> → <tt>(= (hash obj1) (hash obj2))</tt>. ++</p> + <p>A hash function <var>h</var> is <var>good</var> for a equivalence predicate <var>e</var> if it + distributes the result numbers (<var>hash values</var>) for non-equal objects (by + <var>e</var>) as uniformly as possible over the numeric range of hash values, +@@ -360,44 +381,45 @@ especially in the case when some (non-equal) objects resemble each other + by e.g. having common subsequences. This definition is vague but should + be enough to assert that e.g. a constant function is <em>not</em> a good hash + function. +- +-<p>When the definition of <a href="srfi-69.html#mkh">make-hash-table</a> above talks about an ++</p> ++<p>When the definition of <a href="#mkh">make-hash-table</a> above talks about an + <q>appropriate</q> hashing function for <var>e</var>, it means a hashing function that + gives decent performance (for the hashing operation) while being both + acceptable and good for <var>e</var>. This definition, too, is intentionally + vague. +- +-<p>Procedure: <a name="hsh">hash</a> <var>object</var> [ <var>bound</var> ] → <var>integer</var> +- ++</p> ++<p>Procedure: <a name="hsh">hash</a> <var>object</var> [ <var>bound</var> ] → <var>integer</var> ++</p> + <p>Produces a hash value for <var>object</var> in the range ( 0, <var>bound</var> (. If + <var>bound</var> is not given, the implementation is free to choose any bound, + given that the default bound is greater than the size of any imaginable + hash table in a normal application. (This is so that the implementation + may choose some very big value in fixnum range for the default bound.) + This hash function is acceptable for <tt>equal?</tt>. +- +-<p>Procedure: <a name="strng">string-hash</a> <var>string</var> [ <var>bound</var> ] → <var>integer</var> +- +-<p>The same as <a href="srfi-69.html#hsh">hash</a>, except that the argument <var>string</var> must be a string. +- +-<p>Procedure: <a name="strng19">string-ci-hash</a> <var>string</var> [ <var>bound</var> ] → <var>integer</var> +- +-<p>The same as <a href="srfi-69.html#strng">string-hash</a>, except that the case of characters in ++</p> ++<p>Procedure: <a name="strng">string-hash</a> <var>string</var> [ <var>bound</var> ] → <var>integer</var> ++</p> ++<p>The same as <a href="#hsh">hash</a>, except that the argument <var>string</var> must be a string. ++</p> ++<p>Procedure: <a name="strng19">string-ci-hash</a> <var>string</var> [ <var>bound</var> ] → <var>integer</var> ++</p> ++<p>The same as <a href="#strng">string-hash</a>, except that the case of characters in + <var>string</var> does not affect the hash value produced. +- +-<p>Procedure: <a name="hshb">hash-by-identity</a> <var>object</var> [ <var>bound</var> ] → <var>integer</var> +- +-<p>The same as <a href="srfi-69.html#hsh">hash</a>, except that this function is only guaranteed to be ++</p> ++<p>Procedure: <a name="hshb">hash-by-identity</a> <var>object</var> [ <var>bound</var> ] → <var>integer</var> ++</p> ++<p>The same as <a href="#hsh">hash</a>, except that this function is only guaranteed to be + acceptable for <tt>eq?</tt>. The reason for providing this function is that + it might be implemented significantly more efficiently than <tt>hash</tt>. + Implementations are encouraged to provide this function as a builtin. ++</p> + +-<h1><a name="mplm">Implementation</a></h1> ++<h2 id="mplm">Implementation</h2> + + <p>This implementation relies on SRFI-9 for distinctness of the hash table + type, and on SRFI-23 for error reporting. Otherwise, the implementation + is pure R5RS. +- ++</p> + <pre> + + (define *default-bound* (- (expt 2 29) 3)) +@@ -657,10 +679,10 @@ is pure R5RS. + + </pre> + +-<h1><a name="Cpr">Copyright</a></h1> +- +-<p>Copyright © Panu Kalliokoski (2005). All Rights Reserved. ++<h2 id="Cpr">Copyright</h2> + ++<p>Copyright © Panu Kalliokoski (2005). All Rights Reserved. ++</p> + <p>Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + <q>Software</q>), to deal in the Software without restriction, including +@@ -668,20 +690,20 @@ without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: +- ++</p> + <p>The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. +- ++</p> + <p>THE SOFTWARE IS PROVIDED <q>AS IS</q>, WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- <hr> +- <address>Editor: <a HREF="mailto:srfi-editors@srfi.schemers.org">David Van Horn</a></address> ++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++</p> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> + Last modified: Wed Sep 14 09:54:51 EDT 2005 +- + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html +index 17cbb0b..056522a 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-7.html +@@ -1,32 +1,51 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 3.2//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-7 ┃ ++┃ Commit: 003fb7613975797261142593df0bbae4467d3c74 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 7: Feature-based program configuration language</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + <body> + +-<H1>Title</H1> ++<h1>SRFI 7: Feature-based program configuration language</h1> + +-SRFI-7: Feature-based program configuration language ++<p>by Richard Kelsey</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 7 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-7/srfi-7.html">https://srfi.schemers.org/srfi-7/srfi-7.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Richard Kelsey ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+7+at+srfi+dotschemers+dot+org">srfi-7@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-7">archive</a>.</p> ++<ul> ++<li>Received: 1999-05-12 ++</li><li>Draft: 1999-05-26--1999-07-26 ++</li><li>Final: 1999-08-19 ++</li></ul> + +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-7/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/05/12 +-<LI>Draft: 1999/05/26-1999/07/26 +-<LI>Final: 1999/08/19 +-</UL> +- +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + <p> +-This SRFI describes a configuration language to be used for specifing ++This SRFI describes a configuration language to be used for specifying + the set of Scheme features or extensions required to run a program. + In addition to a list of required features, a program may also contain + Scheme code to be used only when a particular feature or combination of +@@ -38,7 +57,7 @@ The configuration language is entirely distinct from Scheme; it is + neither embedded in Scheme nor includes Scheme as a subset. + </p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p> + The use of a separate configuration language makes it easy for +@@ -48,48 +67,38 @@ macros to determine which features, and thus which macros, are used + in the program. + </p> + +-<p> See <a href="http://srfi.schemers.org/srfi-0">SRFI 0</a> for a ++<p> See <a href="https://srfi.schemers.org/srfi-0/">SRFI 0</a> for a + rationale for the need for some kind of configuration control. + </p> + +-<H1>Specification</H1> +-<a name="program"></a> +-<a name="requires"></a> +-<a name="code"></a> +-<a name="feature-cond"></a> +-<a name="and"></a> +-<a name="or"></a> +-<a name="not"></a> +-<a name="else"></a> ++<h2>Specification</h2> + +-<H2>Syntax</H2> ++<h3>Syntax</h3> + +-<p> +-<pre> ++<pre id="program"> + <program> --> (program <program clause>+) + + <program clause> +- --> (requires <feature identifier>+) ++ --> (<span id="requires">requires</span> <feature identifier>+) + | (files <filename>*) +- | (code <Scheme expression, definition, or syntax definition>*) +- | (feature-cond <feature-cond clause>+) +- | (feature-cond <feature-cond clause>* (else <program clause>+)) ++ | (<span id="code">code</span> <Scheme expression, definition, or syntax definition>*) ++ | (<span id="feature-cond">feature-cond</span> <feature-cond clause>+) ++ | (feature-cond <feature-cond clause>* (<span id="else">else</span> <program clause>+)) + + <feature-cond clause> + --> (<feature requirement> <program clause>+) + + <feature requirement> + --> <feature identifier> +- | (and <feature requirement>*) +- | (or <feature requirement>*) +- | (not <feature requirement>) ++ | (<span id="and">and</span> <feature requirement>*) ++ | (<span id="or">or</span> <feature requirement>*) ++ | (<span id="not">not</span> <feature requirement>) + + <feature identifier> + --> a symbol which is the name of a SRFI + </pre> +-</p> + +-<H2>Semantics</H2> ++<h3>Semantics</h3> + <p> + The configuration language is distinct from Scheme. Given a set of + available features a <code><program></code> can be converted into a +@@ -109,7 +118,7 @@ compiles a program into an executable file. + given below. The ordering of the clauses in a <code><program></code> + determines the order of the forms in the resultant Scheme program. + +-<p> In processing the <code>REQUIRES</code> and ++</p><p> In processing the <code>REQUIRES</code> and + <code>FEATURE-COND</code> clauses in a <code><program></code>, + an implementation should be consistent with some fixed set of present + and absent features. An implementation may analyze a <code><program></code> +@@ -132,14 +141,16 @@ same <code><program></code>. + <dd>The forms in <body> are added to the program.</dd> + + <dt><code>(feature-cond <feature-cond clause>+)</code></dt> +- <dd>The meaning of a <code>FEATURE-COND</code> clause is that of the ++ <dd> ++<p> ++ The meaning of a <code>FEATURE-COND</code> clause is that of the + <code><program-clause></code>s in the first <code><feature-cond clause></code> whose + <code><implementation-requirement></code> is satisfied by the implementation. + If an <code>ELSE</code> clause is present it is used if and only if no preceding + clause is satisfied; a <code>FEATURE-COND</code> with an + <code>ELSE</code> clause is always satisfied. +- +-<p>If no clause can be satisified the <code><program></code> cannot be evaluated in ++</p> ++<p>If no clause can be satisfied the <code><program></code> cannot be evaluated in + the implementation.</p> + + <p> +@@ -163,10 +174,11 @@ The meaning of the <code><implementation requirement></code>s is as follow + + <tr><td><code>(not x)</code></td><td>satisfied if <code>X</code> is not satisfied</td></tr> + </table> +- ++ </dd> + </dl> + +-<H1>Implementation</H1> ++ ++<h2>Implementation</h2> + + <p> Two implementations are provided here. The first is a + <code>PROCESS-PROGRAM</code> function that converts a +@@ -184,7 +196,6 @@ an (implementation-dependent) method for evaluating the forms returned by + <code>PROCESS-PROGRAM</code>. + </p> + +-<p> + <pre> + (define (process-program program features) + (call-with-current-continuation +@@ -271,17 +282,17 @@ an (implementation-dependent) method for evaluating the forms returned by + '() + (cons next (label))))))) + (read-files (cdr filenames))))) +-</pre></p> ++</pre> + + <p> + The second implementation is a <code>PROGRAM</code> macro that implements + the configuration language in terms of the <code>COND-EXPAND</code> +-syntax of <a href="http://srfi.schemers.org/srfi-0">SRFI 0</a>. ++syntax of <a href="https://srfi.schemers.org/srfi-0/">SRFI 0</a>. + Note that this implementation requires that <code>LOAD</code> use the current + evaluation environment. + </p> + +-<p><pre> ++<pre> + (define-syntax program + (syntax-rules (requires files code feature-cond) + ((program) +@@ -302,11 +313,12 @@ evaluation environment. + more ...) + (begin (cond-expand (requirement (program stuff ...)) ...) + (program more ...))))) +-</pre></p> +- +-<H1>Copyright</H1> ++</pre> + ++<h2>Copyright</h2> ++<p> + Copyright (C) Richard Kelsey (1999). All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the +@@ -330,8 +342,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <hr /> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html +index a22c3d6..f8a75e7 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-71.html +@@ -1,46 +1,54 @@ +-<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-71 ┃ ++┃ Commit: 1b4b66eb3eed94c4bb564249f98491da4c23cc6d ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 71: Extended LET-syntax for multiple values</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 71: Extended LET-syntax for multiple values</h1> + +-Extended LET-syntax for multiple values ++<p>by <a href="mailto:sebastian.egner-AT-philips.com">Sebastian Egner</a></p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 71 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-71/srfi-71.html">https://srfi.schemers.org/srfi-71/srfi-71.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-<a href="mailto:sebastian.egner-AT-philips.com">Sebastian Egner</a> +- +-<p> +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-To +-provide input on this SRFI, please <CODE> +-<A HREF="mailto:srfi-71@srfi.schemers.org">mailto:srfi-71@srfi.schemers.org</A></CODE>. +-See <A HREF="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</A> to subscribe to the list. You can access the discussion via +-<A HREF="http://srfi.schemers.org/srfi-71/mail-archive/maillist.html">the +-archive of the mailing list</A>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-71/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-</p> +-<UL> +- <LI>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-71/srfi-71.html?rev=1.1">2005/05/16</a></LI> +- <li>Draft: 2005/05/16 - 2005/07/14</li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-71/srfi-71.html?rev=1.2">2005/05/18</a> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-71/srfi-71.html?rev=1.3">2005/08/01</a> +- <li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-71/srfi-71.html?rev=1.6">2005/08/12</a> +-</UL> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+71+at+srfi+dotschemers+dot+org">srfi-71@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-71">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-71/srfi-71-1.1.html">2005-05-16</a></li> ++ <li>Draft: 2005-05-16--2005-07-14</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-71/srfi-71-1.2.html">2005-05-18</a> ++ </li><li>Revised: <a href="https://srfi.schemers.org/srfi-71/srfi-71-1.3.html">2005-08-01</a> ++ </li><li>Final: <a href="https://srfi.schemers.org/srfi-71/srfi-71-1.6.html">2005-08-12</a> ++</li></ul> + + +-<H1>Abstract</H1> ++<h2>Abstract</h2> + ++<p> + This SRFI is a proposal for extending <code>let</code>, + <code>let*</code>, and <code>letrec</code> + for receiving multiple values. +@@ -48,16 +56,19 @@ The syntactic extension is fully compatible with the existing syntax. + It is the intention that single-value bindings, + i.e. <code>(let ((var expr)) ...)</code>, and + multiple-value binding can be mixed freely and conveniently. ++</p> + <p> + The most simple form of the new syntax is best explained by an example: +-<p> +-<pre>(define (quo-rem x y) ++</p> ++<pre> ++(define (quo-rem x y) + (values (quotient x y) (remainder x y))) + + (define (quo x y) + (let ((q r (quo-rem x y))) + q)) + </pre> ++<p> + The procedure <code>quo-rem</code> delivers two values to + its continuation. These values are received as <code>q</code> + and <code>r</code> in the <code>let</code>-expression of the +@@ -65,13 +76,17 @@ procedure <code>quo</code>. + In other words, the syntax of <code>let</code> is extended such + that several variables can be specified---and these variables + receive the values delivered by the expression <code>(quo-rem x y)</code>. ++</p> + <p> + The syntax of <code>let</code> is further extended to cases in which + a rest argument receives the list of all residual values. + Again by example, +-<pre>(let (((values y1 y2 . y3+) (foo x))) ++</p> ++<pre> ++(let (((values y1 y2 . y3+) (foo x))) + body) + </pre> ++<p> + In this example, <code>values</code> is a syntactic keyword + indicating the presence of multiple values to be received, + and <code>y1</code>, <code>y2</code>, and <code>y3+</code>, +@@ -82,6 +97,7 @@ The syntactic keyword <code>values</code> allows receiving + all values as in <code>(let (((values . xs) (foo x))) body)</code>. + It also allows receiving no values at all as in + <code>(let (((values) (for-each foo list))) body)</code>. ++</p> + <p> + A common application of binding multiple values is + decomposing data structures into their components. +@@ -90,9 +106,12 @@ The procedure <code>uncons</code> (defined below) + decomposes a pair <code>x</code> into its car and its cdr + and delivers them as two values to its continuation. + Then an extended <code>let</code> can receive these values: +-<pre>(let ((car-x cdr-x (uncons x))) ++</p> ++<pre> ++(let ((car-x cdr-x (uncons x))) + (foo car-x cdr-x)) + </pre> ++<p> + Of course, for pairs this method is probably neither faster + nor clearer than using the procedures <code>car</code> + and <code>cdr</code>. +@@ -107,16 +126,19 @@ point already as both quotient and remainder are probably + computed by a common exact division algorithm. + (And often caching is used to avoid executing this + algorithm twice as often as needed.) ++</p> + <p> + As the last feature of this SRFI, a mechanism is specified + to store multiple values in heap-allocated data structures. +-For this purpose, <code>values->list</code> and <code>values->vector</code> ++For this purpose, <code>values->list</code> and <code>values->vector</code> + construct a list (a vector, resp.) storing all values delivered + by evaluating their argument expression. + Note that these operations cannot be procedures. ++</p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + ++<p> + My original motivation for writing this SRFI is my unhappiness with + the current state of affairs in Scheme with respect to multiple values. + Multiple values are mandatory in the +@@ -124,6 +146,7 @@ Revised^5 Report on the Algorithmic + Language Scheme (<a href="#R5RS">R5RS</a>), + and they are fully available in all major Scheme implementations. + Yet there is often a painful hesitation about using them. ++</p> + <p> + The reason for this hesitation is that multiple values are + nearly fully integrated into Scheme---but not quite. +@@ -136,6 +159,7 @@ and I understand this SRFI as a minor contribution + "placing the last corner stone". + But first a very brief history of multiple values in Scheme, + as far as relevant for this SRFI. ++</p> + <p> + <a href="#R5RS">R5RS</a> specifies the procedures <code>values</code> + and <code>call-with-values</code> for passing any number of values +@@ -143,6 +167,7 @@ from a producer procedure to a consumer procedure. + This is the only construct in R5RS + dealing with multiple values explicitly, and it is sufficient + to implement anything that can be implemented for multiple values. ++</p> + <p> + However, as John David Stone observed in <a href="#SRFI8">SRFI 8</a>, + the mechanism exposes explicitly how multiple values are +@@ -155,6 +180,7 @@ by adding the special form + for receiving several values produced by the expression + in variables specified by <code><formals></code> and + using them in the body. ++</p> + <p> + The major limitation of <code>receive</code> is that it can only + handle a single expression, which means programs dealing with +@@ -173,17 +199,19 @@ to the list of all values delivered by <code>x</code> (as in <a href="#SRFI11">S + Or is <code>x</code> to deliver a single value to be + bound to <code>v</code> (as in <code>let</code>)? + Refer to the +-<a href="http://srfi.schemers.org/srfi-11/mail-archive/threads.html">discussion ++<a href="https://srfi.schemers.org/srfi-11/mail-archive/threads.html">discussion + archive of SRFI 11</a> for details. + Moreover, <code>let-values</code> suffers from "parenthesis complexity", + despite Scheme programmers are tolerant to braces. ++</p> + <p> +-Eli Barzilay's <a href="#Eli">Swindle</a> library (for MzScheme) on ++Eli Barzilay's <a href="#Swindle">Swindle</a> library (for MzScheme) on + the other hand redefines let to include multiple-values and internal + procedures: The syntactic keyword <code>values</code> indicates the + presence of multiple values, while additional parentheses (with the + syntax of <code><formals></code>) + indicate a <code>lambda</code>-expression as right-hand side. ++</p> + <p> + This SRFI follows Eli's approach, while keeping the syntax + simple (few parentheses and concepts) and adding tools for +@@ -194,6 +222,7 @@ This is achieved by extending the syntax in two different + ways (multiple left-hand sides or a syntactic keyword) + and adding operations to convert between (implicitly passed) + values and (first class) data structures. ++</p> + <p> + Finally, I would like to mention that Oscar Waddell et al. + describe an efficient compilation method for Scheme's +@@ -203,25 +232,30 @@ to as a basis for internal <code>define</code>. + I expect their compilation method (and <code>letrec*</code>) + and this SRFI to be fully compatible with one another, + although I have not checked this claim by way of implementation. ++</p> + +-<H1>Specification</H1> ++<h2 id="let">Specification</h2> + +-<a name="let"></a>The syntax of Scheme (<a href="#R5RS">R5RS</a>, Section 7.1.3.) ++<p> ++The syntax of Scheme (<a href="#R5RS">R5RS</a>, Section 7.1.3.) + is extended by replacing the existing production: +- +-<pre><binding spec> --> (<variable> <expression>) ++</p> ++<pre> ++<binding spec> --> (<variable> <expression>) + </pre> +- ++<p> + by the three new productions +- +-<pre><binding spec> --> ((values <variable>*) <expression>) ++</p> ++<pre> ++<binding spec> --> ((values <variable>*) <expression>) + <binding spec> --> ((values <variable>* . <variable>) <expression>) + <binding spec> --> (<variable>+ <expression>) + </pre> +- ++<p> + The form <code>(<variable>+ <expression>)</code> is just + an abbreviation for <code>((values <variable>+) <expression>)</code>, + and it includes the original <code><binding spec></code> of <a href="#R5RS">R5RS</a>. ++</p> + <p> + The first two forms are evaluated as follows: The variables are bound and + the expression is evaluated according to the enclosing construct +@@ -229,6 +263,7 @@ the expression is evaluated according to the enclosing construct + However, the expression may deliver any number of values to its continuation, + which stores these values into the variables specified, + possibly allocating a rest list in case of the <code>. <variable></code> form. ++</p> + <p> + The number of values delivered by the expression must match the + number of values expected by the binding specification. +@@ -236,12 +271,16 @@ Otherwise an error is raised, as <code>call-with-values</code> would. + This implies in particular, that each binding of a named let involves + exactly one value, because this binding can also be an argument to a + lambda-expression. ++</p> + + <h3>Standard operations</h3> + ++<p> + The following procedures, specified in terms of standard procedures, + are added to the set of standard procedures: +-<pre><a name="uncons"></a>(define (uncons pair) ++</p> ++<pre> ++<span id="uncons">(define (uncons pair)</span> + (values (car pair) (cdr pair))) + + (define (uncons-2 list) +@@ -253,20 +292,22 @@ are added to the set of standard procedures: + (define (uncons-4 list) + (values (car list) (cadr list) (caddr list) (cadddr list) (cddddr list))) + +-<a name="uncons-cons"></a>(define (uncons-cons alist) ++<span id="uncons-cons">(define (uncons-cons alist)</span> + (values (caar alist) (cdar alist) (cdr alist))) + +-<a name="unlist"></a>(define (unlist list) ++<span id="unlist">(define (unlist list)</span> + (apply values list)) + +-<a name="unvector"></a>(define (unvector vector) +- (apply values (vector->list vector))) ++<span id="unvector">(define (unvector vector)</span> ++ (apply values (vector->list vector))) + </pre> ++<p> + These procedures decompose the standard concrete data structures + (pair, list, vector) and deliver the components as values. + It is an error if the argument cannot be decomposed as expected. + Note that the procedures are not necessarily implemented by + the definition given above. ++</p> + <p> + The preferred way of decomposing a list into the first two elements + and the rest list is <code>(let ((x1 x2 x3+ (uncons-2 x))) body)</code>, +@@ -275,33 +316,38 @@ This is <i>not</i> equivalent to + <code>(let (((values x1 x2 . x3+) (unlist x))) body)</code> + because the latter binds <code>x3+</code> to a newly allocated + copy of <code>(cddr x)</code>. ++</p> + <p> + Finally, the following two macros are added to the standard macros: +- +-<pre><a name="values2list"></a>(values->list <expression>) +-<a name="values2vector"></a>(values->vector <expression>) ++</p> ++<pre> ++<span id="values2list">(values->list <expression>)</span> ++<span id="values2vector">(values->vector <expression>)</span> + </pre> +- ++<p> + These operation receive all values (if any) delivered by their + argument expression and return a newly allocated list (vector, resp.) + of these values. +-Note that <code>values->list</code> is <i>not</i> the same as ++Note that <code>values->list</code> is <i>not</i> the same as + <code>list</code> (the procedure returning the list of its arguments). ++</p> + +-<H1>Design Rationale</H1> ++<h2>Design Rationale</h2> + + <h3>Which alternatives designs for the syntax were considered?</h3> + ++<p> + This SRFI defines two notations for receiving several values: + Using the keyword <code>values</code>, + or simply listing the variables if there is at least one. + There are several alternatives for this design, + some of which were proposed during the discussion. +-(Refer in particular to <a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00000.html">msg00000</a>, +-<a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00001.html">msg00001</a>, and +-<a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00002.html">msg00002</a>, +-<a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00007.html">msg00007</a>.) ++(Refer in particular to <a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00000.html">msg00000</a>, ++<a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00001.html">msg00001</a>, and ++<a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00002.html">msg00002</a>, ++<a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00007.html">msg00007</a>.) + The alternatives considered include: ++</p> + <ol> + <li>Just listing the variables (no syntactic keyword at all) as in + <code>(let ((x1 x2 expr)) body)</code>.</li> +@@ -316,20 +362,21 @@ rest list as in <code>(let ((x1 x2 (rest x3+) expr)) body)</code>.</li> + <li>Using the <code><formals></code> syntax of + <a href="#R5RS">R5RS</a> as in + <code>(let (((x1 x2 . x3+) expr)) body)</code>. +-<li>Mimicking <code><formals></code> but with ++</li><li>Mimicking <code><formals></code> but with + one level of parentheses removed as in + <code>(let ((x1 x2 . x3+ expr)) body)</code>.</li> + <li>As the previous but with additional syntax for +-"no values" and "just a rest", e.g. ++"no values" and "just a rest", e.g. + <code>(let ((! expr)) body)</code> and + <code>(let ((xs . expr)) body)</code>. +-</ol> ++</li></ol> + <p> + The requirements for the design are + compatibility with the existing <code>let</code>, + concise notation for the frequent use cases, + robustness against most common mistakes, and + full flexibility of receiving values. ++</p> + <p> + For the sake of compatibility, + only modifications of <code><binding spec></code> were +@@ -340,9 +387,10 @@ Concerning concise notation, by far the most convenient notation + is <i>listing the variables</i>. + As this notation also covers the existing syntax, it was adopted + as the basis of the extension to be specified. ++</p> + <p> + The <i>listing the variables</i> notation is limited by the fact that +-the preferred marker for a rest list ("<code>.</code>") ++the preferred marker for a rest list ("<code>.</code>") + cannot follow an opening parenthesis as in + <code>(let ((. xs expr)) body)</code>, + nor that it can be followed by two syntactic elements as in +@@ -350,6 +398,7 @@ nor that it can be followed by two syntactic elements as in + Lifting these restrictions would require major modifications + in unrelated parts of the Scheme syntax, which is not an + attractive option. ++</p> + <p> + Another problematic aspect of the <i>listing the variables</i> notation + is the case of no variables at all. +@@ -360,29 +409,34 @@ it seriously harms syntactic robustness: + syntactically correct and could easily be confused with one another. + For this reason, the notation of listing the variables was + restricted to one or more variables. ++</p> + <p> + This leaves the problem of extending the notation in order to +-cover rest arguments and the "no values"-case. ++cover rest arguments and the "no values"-case. + This can either be done <i>ad hoc</i>, covering the open cases, + or by adding a general notation covering all cases. + In view of readability and uniformity (useful when code gets + processed automatically) the latter approach was chosen. + This has resulted in the design specified in this SRFI. ++</p> + +-<h3>Why is <code>values</code> needed in the "zero values"-case?</h3> ++<h3>Why is <code>values</code> needed in the "zero values"-case?</h3> + ++<p> + The syntax specified in this SRFI allows zero variables being + bound in a binding specification using the syntax + <code>(let (((values) (for-each foo (bar)))) body)</code>. + An alternative is allowing <code>(<expression>)</code> + as a binding specification. +-(Refer to the discussion archive starting at <a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00001.html">msg00001</a>.) ++(Refer to the discussion archive starting at <a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00001.html">msg00001</a>.) ++</p> + <p> + The syntax specified in this SRFI is designed for static + detection of the most frequent types (forgotten parentheses). + For example, writing + <code>(let ((values) (for-each foo (bar))) body)</code> + is not a well-formed let-expression in this SRFI. ++</p> + <p> + In the alternative syntax, both + <code>(let (((for-each foo (bar)))) body)</code> +@@ -396,29 +450,36 @@ the error will probably manifest itself at the moment + <code>(bar)</code> fails to deliver exactly two values. + Unless it does, in which case the error must manifest itself much + further downstream from the fact that <code>foo</code> never got called. ++</p> + <p> + In order to avoid this sort of expensive typos, + the syntax proposed in this SRFI is more verbose + than it needs to be. ++</p> + + <h3>Why not also include a syntax for procedures?</h3> + ++<p> + This SRFI is a proposal for extending the syntax of <code>let</code> + etc. in order to include multiple values. + It is also desirable to extend the syntax of <code>let</code> + for simplifying the definition of local procedures. + (For example, as in <a href="#Swindle">Swindle</a>.) + However, this SRFI does not include this feature. ++</p> + <p> + The reason I have chosen not restrict this SRFI to a syntax + for multiple values is simplicity. ++</p> + + <h3>Why the names <code>unlist</code> etc.?</h3> + ++<p> + An alternative naming convention for the decomposition +-operation <code>unlist</code> is <code>list->values</code>, ++operation <code>unlist</code> is <code>list->values</code>, + which is more symmetric with respect to its +-inverse operation <code>values->list</code>. ++inverse operation <code>values->list</code>. ++</p> + <p> + This symmetry ends, however, as soon as more complicated + data structures with other operations are involved. +@@ -426,21 +487,25 @@ Then it becomes apparent that the same data structure can + support different decomposition operations: + A double-ended queue (deque) for example supports splitting off + the head and splitting of the tail; and neither of these +-operations should be named <code>deque->values</code>. ++operations should be named <code>deque->values</code>. + The <code>un</code>-convention covers this in a natural way. ++</p> + <p> + Please also refer to the double-ended queue (deque) example +-in <a href="examples.scm">examples.scm</a> to see how to ++in <a href="https://srfi.schemers.org/srfi-71/examples.scm">examples.scm</a> to see how to + use decomposition procedures for dealing with data structures. ++</p> + + <h3>Which decomposition operations are included?</h3> + ++<p> + The particular set of operations specified in this SRFI + for decomposing lists represents a trade-off between limiting + the number of operations and convenience. ++</p> + <p> + As Al Petrofsky has pointed out during the discussion +-(<a href="http://srfi.schemers.org/srfi-71/mail-archive/msg00018.html"> ++(<a href="https://srfi.schemers.org/srfi-71/mail-archive/msg00018.html"> + msg00018</a>) it is not sufficient to have only + <code>unlist</code> as this will copy the rest list. + For this reason specialized decomposition operations +@@ -448,15 +513,17 @@ for splitting off the first 1, ..., 4 elements are + provided, and a decomposition operation expecting the + first element to be a pair itself. + These appear to be the most common cases. ++</p> + +-<H1>Implementation</H1> ++<h2>Implementation</h2> + ++<p> + The reference implementation is written in <a href="#R5RS">R5RS</a> + using hygienic macros, only. + It is not possible, however, to portably detect read access to + an uninitialized variable introduced by <code>letrec</code>. + The definition of the actual functionality can be found +-<a href="letvalues.scm">here</a>. ++<a href="https://srfi.schemers.org/srfi-71/letvalues.scm">here</a>. + The implementation defines macros <code>srfi-let/*/rec</code> etc. + in terms of <code>r5rs-let/*/rec</code>. + Implementors may use this to redefine (or even re-implement) +@@ -464,86 +531,93 @@ Implementors may use this to redefine (or even re-implement) + while providing implementations of <code>r5rs-let/*/rec</code>. + An efficient method for the latter is given in <a href="#Fix">Fixing Letrec</a> + by O. Waddell et al. ++</p> + <p> + <i>R5RS:</i> + For trying out the functionality, a complete implementation under +-<a href="#R5RS">R5RS</a> can be found <a href="letvalues-r5rs.scm">here</a>. ++<a href="#R5RS">R5RS</a> can be found <a href="https://srfi.schemers.org/srfi-71/letvalues-r5rs.scm">here</a>. + It defines <code>r5rs-let/*/rec</code> in terms of <code>lambda</code> + and redefines <code>let/*/rec</code> as <code>srfi-let/*/rec</code>. + This may not be the most efficient implementation, because many + Scheme systems handle <code>let</code> etc. specially and do not + reduce it into <code>lambda</code> ++</p> + <p> + <i>PLT 208:</i> +-The implementation found <a href="letvalues-plt.scm">here</a> +-uses <a href="#PLT">PLT</a>'s module system for exporting ++The implementation found <a href="https://srfi.schemers.org/srfi-71/letvalues-plt.scm">here</a> ++uses PLT's module system for exporting + <code>srfi-let/*/rec</code> + under the name of <code>let/*/rec</code>, while defining + <code>r5rs-let/*/rec</code> as a copy of the built-in + <code>let/*/rec</code>. This code should be efficient. ++</p> + <p> + Examples using the new functionality +-can be found in <a href="examples.scm">examples.scm</a>. ++can be found in <a href="https://srfi.schemers.org/srfi-71/examples.scm">examples.scm</a>. ++</p> + +-<H1>References</H1> ++<h2>References</h2> + + <table> + + <tr> + <td><a name="R5RS">[R5RS]</a> +-<td>Richard Kelsey, William Clinger, and Jonathan Rees (eds.): ++</td><td>Richard Kelsey, William Clinger, and Jonathan Rees (eds.): + Revised^5 Report on the Algorithmic Language Scheme of + 20 February 1998. + Higher-Order and Symbolic Computation, Vol. 11, No. 1, September 1998. + <a href="http://schemers.org/Documents/Standards/R5RS/"> + http://schemers.org/Documents/Standards/R5RS/</a>. +-</tr> ++</td></tr> + + <tr> + <td><a name="SRFI8">[SRFI 8]</a> +-<td>John David Stone: <code>Receive</code>: Binding to multiple values. +-<a href="http://srfi.schemers.org/srfi-8/">http://srfi.schemers.org/srfi-8/</a> +-</tr> ++</td><td>John David Stone: <code>Receive</code>: Binding to multiple values. ++<a href="srfi-8.html">http://srfi.schemers.org/srfi-8/</a> ++</td></tr> + + <tr> + <td><a name="SRFI11">[SRFI 11]</a> +-<td>Lars T. Hansen: Syntax for receiving multiple values. +-<a href="http://srfi.schemers.org/srfi-11/">http://srfi.schemers.org/srfi-11/</a> +-</tr> ++</td><td>Lars T. Hansen: Syntax for receiving multiple values. ++<a href="srfi-11.html">http://srfi.schemers.org/srfi-11/</a> ++</td></tr> + + <tr> +-<td><a name="Eli">[Swindle]</a> +-<td>Eli Barzilay: Swindle, documentation for "base.ss" (Swindle Version 20040908.) ++<td><a name="Swindle">[Swindle]</a> ++</td><td>Eli Barzilay: Swindle, documentation for "base.ss" (Swindle Version 20040908.) + <a href="http://www.cs.cornell.edu/eli/Swindle/base-doc.html#let">http://www.cs.cornell.edu/eli/Swindle/base-doc.html#let</a> +-</tr> ++</td></tr> + + <tr> + <td><a name="Fix">[Fix]</a> +-<td>O. Waddell, D. Sarkar, R. K. Dybvig: ++</td><td>O. Waddell, D. Sarkar, R. K. Dybvig: + Fixing Letrec: A Faithful Yet Efficient Implementation of Scheme's + Recursive Binding Construct. To appear, 2005. + <a href="http://www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf">http://www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf</a> +-</tr> ++</td></tr> + + </table> + + +-<H1>Copyright</H1> ++<h2>Copyright</h2> ++<p> + Copyright (c) 2005 Sebastian Egner. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: ++</p> + <p> + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ++</p> + <p> + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- +- <hr> ++</p> ++ <hr /> + <address>Author: <a href="mailto:sebastian.egner@philips.com">Sebastian Egner</a></address> +- <address>Editor: <a +- href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Created: Fri Apr 29 09:30:00 CEST 2005 --> + <!-- hhmts start --> +-Last modified: Sun Sep 11 16:07:38 CEST 2005 ++Last modified: Sun Jan 28 13:40:16 MET 2007 + <!-- hhmts end --> + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html +index 50be385..6058742 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-74.html +@@ -1,60 +1,449 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html> +-<body> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> +-<title>SRFI 74: Octet-Addressed Binary Blocks</title> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-74 ┃ ++┃ Commit: 63e0cc6d44d5375df4ec77b74b225efe9c0cdaee ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 74: Octet-Addressed Binary Blocks</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> +-<H1>Title</H1> +- +-Octet-Addressed Binary Blocks ++<h1>SRFI 74: Octet-Addressed Binary Blocks</h1> + +-<H1>Authors</H1> ++<p>by Michael Sperber</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 74 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-74/srfi-74.html">https://srfi.schemers.org/srfi-74/srfi-74.html</a>.</p></blockquote></blockquote></blockquote> + +-Michael Sperber ++<h2>Status</h2> + + <p> +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a HREF="http://srfi.schemers.org/srfi-process.html">here</a>. +-To +-provide input on this SRFI, please <code> +-<a HREF="mailto:srfi-74@srfi.schemers.org">mailto:srfi-74@srfi.schemers.org</a></code>. +-See <a HREF="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access previous messages via +-<a HREF="http://srfi.schemers.org/srfi-74/mail-archive/maillist.html">the +-archive of the mailing list</a>. ++ This SRFI is currently in <em>final</em> status. Here ++ is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> ++ of each status that a SRFI can hold. To provide input on this SRFI, please ++ send email ++ to <code><a href="mailto:srfi+minus+74+at+srfi+dotschemers+dot+org">srfi-74@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. ++ To subscribe to the list, ++ follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these ++ instructions</a>. You can access previous messages via the mailing ++ list <a href="https://srfi-email.schemers.org/srfi-74">archive</a>. ++</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-74/srfi-74-1.1.html">2005-07-06</a></li> ++ <li>Draft: 2005-07-06--2005-09-04</li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-74/srfi-74-1.2.html">2005-07-22</a> ++ </li><li>Revised: <a href="https://srfi.schemers.org/srfi-74/srfi-74-1.3.html">2005-12-04</a> ++ </li><li>Final: <a href="https://srfi.schemers.org/srfi-74/srfi-74-1.4.html">2005-12-15</a> ++</li></ul> ++<h2>Abstract</h2> ++<p> ++ This SRFI defines a set of procedures for creating, accessing, and ++ manipulating octet-addressed blocks of binary data, in ++ short, <i>blobs</i>. The SRFI provides access primitives for fixed-length ++ integers of arbitrary size, with specified endianness, and a choice of ++ unsigned and two's complement representations. ++</p> ++<h2>Rationale</h2> ++<p> ++ Many applications must deal with blocks of binary data by accessing them in ++ various ways---extracting signed or unsigned numbers of various sizes. Such ++ an application can use octet vectors as ++ in <a href="srfi-66.html">SRFI 66</a> or any of the ++ other types of homogeneous vectors ++ in <a href="srfi-4.html">SRFI 4</a>, but these both ++ only allow retrieving the binary data of one type. ++</p> ++<p> ++ This is awkward in many situations, because an application might access ++ different kinds of entities from a single binary block. Even for uniform ++ blocks, the disjointness of the various vector data types in SRFI 4 means ++ that, say, an I/O API needs to provide an army of procedures for each of ++ them in order to provide efficient access to binary data. ++</p> ++<p> ++ Therefore, this SRFI provides a <em>single</em> type for blocks of binary ++ data with multiple ways to access that data. It deals only with integers in ++ various sizes with specified endianness, because these are the most frequent ++ applications. Dealing with other kinds of binary data, such as ++ floating-point numbers or variable-size integers would be natural ++ extensions, but are left for a future SRFI. ++</p> ++<h2>Specification</h2> ++<h3>General remarks</h3> ++<p> ++ Blobs are objects of a new type. Conceptually, a blob represents a sequence ++ of octets. ++</p> ++<p> ++ Scheme systems implementing both SRFI 4 and/or SRFI 66 and this SRFI may or ++ may not use the same type for u8vector and blobs. They are encouraged to do ++ so, however. ++</p> ++<p> ++ As with u8vectors, the length of a blob is the number of octets it contains. ++ This number is fixed. A valid index into a blob is an exact, non-negative ++ integer. The first octet of a blob has index 0, the last octet has an index ++ one less than the length of the blob. ++</p> ++<p> ++ Generally, the access procedures come in different flavors according to the ++ size of the represented integer, and ++ the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a> of the ++ representation. The procedures also distinguish signed and unsigned ++ representations. The signed representations all ++ use <a href="http://en.wikipedia.org/wiki/Two's_complement">two's ++ complement</a>.</p> ++<p> ++ For procedures that have no "natural" return value, this SRFI often uses the ++ sentence: ++</p> ++<p> ++ <em>The return values are unspecified.</em> ++</p> ++<p> ++ This means that number of return values and the return values are ++ unspecified. However, the number of return values is such that it is ++ accepted by a continuation created by <code>begin</code>. Specifically, on ++ Scheme implementations where continuations created by <code>begin</code> ++ accept an arbitrary number of arguments (this includes most ++ implementations), it is suggested that the procedure return zero return ++ values. ++</p> ++<h3>Interface</h3> ++<dl> ++<dt><code>(endianness </code><code>big</code><code>)</code> (syntax)</dt> ++<dt><code>(endianness </code><code>little</code><code>)</code> (syntax)</dt> ++<dt><code>(endianness </code><code>native</code><code>)</code> (syntax)</dt> ++<dd> ++ <p> ++ <code>(endianness big)</code> and <code>(endianness little)</code> ++ evaluate to two distinct and unique objects representing an endianness. ++ The <code>native</code> endianness evaluates to the endianness of the ++ underlying machine architecture, and must be <code>eq?</code> to ++ either <code>(endianness big)</code> or <code>(endianness little)</code>. ++ </p> ++</dd> ++<dt><code>(blob? </code><var>obj</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns <code>#t</code> if <var>obj</var> is a blob, otherwise ++ returns <code>#f</code>. ++ </p> ++</dd> ++<dt><code>(make-blob </code><var>k</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns a newly allocated blob of <var>k</var> octets, all of them 0. ++ </p> ++</dd> ++<dt><code>(blob-length </code><var>blob</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns the number of octets in <var>blob</var> as an exact integer. ++ </p> ++</dd> ++<dt><code>(blob-u8-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s8-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>K</var> must be a valid index of <var>blob</var>. ++ </p> ++ <p> ++ <code>Blob-u8-ref</code> returns the octet at index <var>k</var> ++ of <var>blob</var>. ++ </p> ++ <p> ++ <code>Blob-s8-ref</code> returns the exact integer corresponding to the ++ two's complement representation at index <var>k</var> ++ of <var>blob</var>. ++ </p> ++</dd> ++<dt><code>(blob-u8-set! </code><var>blob</var> <var>k</var> <var>octet</var><code>)</code></dt> ++<dt><code>(blob-s8-set! </code><var>blob</var> <var>k</var> <var>byte</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>K</var> must be a valid index ++ of <var>blob</var>.</p><p><code>Blob-u8-set!</code> ++ stores <var>octet</var> in element <var>k</var> of <var>blob</var>. ++ </p> ++ <p> ++ <var>Byte</var>, must be an exact integer in the interval {-128, ..., ++ 127}. <code>Blob-u8-set!</code> stores the two's complement representation ++ of <var>byte</var> in element <var>k</var> of <var>blob</var>. ++ </p> ++ <p>The return values are unspecified.</p> ++</dd> ++<dt><code>(blob-uint-ref </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-sint-ref </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-uint-set! </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-sint-set! </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>Size</var> must be a positive exact integer. <var>K</var> must be a ++ valid index of <var>blob</var>; so must the indices {<var>k</var>, ++ ..., <var>k</var> + <var>size</var> - 1}. <var>Endianness</var> must be an ++ endianness object. ++ </p> ++ <p> ++ <code>Blob-uint-ref</code> retrieves the exact integer corresponding to ++ the unsigned representation of size <var>size</var> and specified ++ by <var>endianness</var> at indices {<var>k</var>, ..., <var>k</var> ++ + <var>size</var> - 1}. ++ </p> ++ <p> ++ <code>Blob-sint-ref</code> retrieves the exact integer corresponding to ++ the two's complement representation of size <var>size</var> and specified ++ by <var>endianness</var> at indices {<var>k</var>, ..., <var>k</var> ++ + <var>size</var> - 1}. ++ </p> ++ <p> ++ For <code>blob-uint-set!</code>, <var>n</var> must be an exact integer in ++ the interval [0, (256^<var>size</var>)-1]. <code>Blob-uint-set!</code> ++ stores the unsigned representation of size <var>size</var> and specified ++ by <var>endianness</var> into the blob at indices {<var>k</var>, ++ ..., <var>k</var> + <var>size</var> - 1}. ++ </p> ++ <p> ++ For <code>blob-uint-set!</code>, <var>n</var> must be an exact integer in ++ the interval [-256^(<var>size</var>-1), ++ (256^(<var>size</var>-1))-1]. <code>Blob-sint-set!</code> stores the two's ++ complement representation of size <var>size</var> and specified ++ by <var>endianness</var> into the blob at indices {<var>k</var>, ++ ..., <var>k</var> + <var>size</var> - 1}. ++ </p> ++</dd> ++<dt><code>(blob-u16-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s16-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u16-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s16-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u16-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s16-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-u16-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s16-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>K</var> must be a valid index of <var>blob</var>; so must the ++ index <var>k</var>+ 1. <var>Endianness</var> must be an endianness ++ object. ++ </p> ++ <p> ++ These retrieve and set two-octet representations of numbers at ++ indices <var>k</var> and <var>k</var>+1, according to the endianness ++ specified by <var>endianness</var>. The procedures with <code>u16</code> ++ in their names deal with the unsigned representation, those ++ with <code>s16</code> with the two's complement representation. ++ </p> ++ <p> ++ The procedures with <code>native</code> in their names employ the native ++ endianness, and only work at aligned indices: <var>k</var> must be a ++ multiple of 2. It is an error to use them at non-aligned indices. ++ </p> ++</dd> ++<dt><code>(blob-u32-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s32-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u32-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s32-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u32-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s32-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-u32-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s32-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>K</var> must be a valid index of <var>blob</var>; so must the indices ++ {<var>k</var>, ..., <var>k</var>+ 3}. <var>Endianness</var> must be an ++ endianness object. ++ </p> ++ <p> ++ These retrieve and set four-octet representations of numbers at indices ++ {<var>k</var>, ..., <var>k</var>+ 3}, according to the endianness ++ specified by <var>endianness</var>. The procedures with <code>u32</code> ++ in their names deal with the unsigned representation, those ++ with <code>s32</code> with the two's complement representation. ++ </p> ++ <p> ++ The procedures with <code>native</code> in their names employ the native ++ endianness, and only work at aligned indices: <var>k</var> must be a ++ multiple of 4. It is an error to use them at non-aligned indices. ++ </p> ++</dd> ++<dt><code>(blob-u64-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s64-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u64-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-s64-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt> ++<dt><code>(blob-u64-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s64-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-u64-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dt><code>(blob-s64-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>K</var> must be a valid index of <var>blob</var>; so must the indices ++ {<var>k</var>, ..., <var>k</var>+ 7}. <var>Endianness</var> must be an ++ endianness object. ++ </p> ++ <p> ++ These retrieve and set eight-octet representations of numbers at indices ++ {<var>k</var>, ..., <var>k</var>+ 7}, according to the endianness ++ specified by <var>endianness</var>. The procedures with <code>u64</code> ++ in their names deal with the unsigned representation, those ++ with <code>s64</code> with the two's complement representation. ++ </p> ++ <p> ++ The procedures with <code>native</code> in their names employ the native ++ endianness, and only work at aligned indices: <var>k</var> must be a ++ multiple of 8. It is an error to use them at non-aligned indices. ++ </p> ++</dd> ++<dt><code>(blob=? </code><var>blob-1</var> <var>blob-2</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns <var>#t</var> if <var>blob-1</var> and <var>blob-2</var> are ++ equal---that is, if they have the same length and equal octets at all ++ valid indices. ++ </p> ++</dd> ++<dt><code>(blob-copy! </code><var>source</var> <var>source-start</var> <var>target</var> <var>target-start</var> <var>n</var><code>)</code></dt> ++<dd> ++ <p> ++ Copies data from blob <var>source</var> to ++ blob <var>target</var>. <var>Source-start</var>, <var>target-start</var>, ++ and <var>n</var> must be non-negative exact integers that satisfy ++ </p> ++ <p> ++ 0 <= <var>source-start</var> <= <var>source-start</var> ++ + <var>n</var> <= <code>(blob-length <var>source</var>)</code> ++ </p> ++ <p> ++ 0 <= <var>target-start</var> <= <var>target-start</var> ++ + <var>n</var> <= <code>(blob-length <var>target</var>)</code> ++ </p> ++ <p> ++ This copies the octets from <var>source</var> at indices ++ [<var>source-start</var>, <var>source-start</var> + <var>n</var>) to ++ consecutive indices in <var>target</var> starting ++ at <var>target-index</var>. ++ </p> ++ <p> ++ This must work even if the memory regions for the source and the target ++ overlap, i.e., the octets at the target location after the copy must be ++ equal to the octets at the source location before the copy. ++ </p> ++ <p> ++ The return values are unspecified. ++ </p> ++</dd> ++<dt><code>(blob-copy </code><var>blob</var><code>)</code></dt> ++<dd> ++ <p> ++ Returns a newly allocated copy of blob <var>blob</var>. ++ </p> ++</dd> ++<dt><code>(blob->u8-list </code><var>blob</var><code>)</code></dt> ++<dt><code>(u8-list->blob </code><var>blob</var><code>)</code></dt> ++<dd> ++ <p> ++ <code>blob->u8-list</code>returns a newly allocated list of the octets ++ of <var>blob</var> in the same ++ order. ++ </p> ++</dd> ++<dd> ++ <p> ++ <code>U8-list->blob</code> returns a newly allocated blob whose ++ elements are the elements of list <var>octets</var>, which must all be ++ octets, in the same order. Analogous to <code>list->vector</code>. ++ </p> ++</dd> ++<dt><code>(blob->uint-list </code><var>size</var> <var>endianness</var> <var>blob</var><code>)</code></dt> ++<dt><code>(blob->sint-list </code><var>size</var> <var>endianness</var> <var>blob</var><code>)</code></dt> ++<dt><code>(uint-list->blob </code><var>size</var> <var>endianness</var> <var>list</var><code>)</code></dt> ++<dt><code>(sint-list->blob </code><var>size</var> <var>endianness</var> <var>list</var><code>)</code></dt> ++<dd> ++ <p> ++ <var>Size</var> must be a positive exact integer. <var>Endianness</var> ++ must be an endianness object. ++ </p> ++ <p> ++ These convert between lists of integers and their consecutive ++ representations according to <var>size</var> and <var>endianness</var> in ++ blobs in the same way ++ as <code>blob->u8-list</code>, <code>blob->s8-list</code>, ++ <code>u8-list->blob</code>, and <code>s8-list->blob</code> do for ++ one-octet representations. ++ </p> ++</dd> ++</dl> + ++<h2>Reference Implementation</h2> ++<p> ++ This <a href="https://srfi.schemers.org/srfi-74/blob.scm">reference implementation</a> makes use ++ of <a href="srfi-23.html">SRFI 23</a> (Error reporting ++ mechanism), <a href="srfi-26.html">SRFI 26</a> ++ (Notation for Specializing Parameters without ++ Currying), <a href="srfi-60.html">SRFI 60</a> (Integers ++ as Bits), and <a href="srfi-66.html">SRFI 66</a> (Octet ++ Vectors). ++</p> ++<h2>Examples</h2> ++<p> ++ The <a href="https://srfi.schemers.org/srfi-74/example.scm">test suite</a> doubles as a source of examples. + </p> ++<h2>References</h2> + <ul> +- <li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-74/srfi-74.html?rev=1.1">2005/07/06</a></li> +- <li>Draft: 2005/07/06 - 2005/09/04</li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-74/srfi-74.html?rev=1.2">2005/07/22</a> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-74/srfi-74.html?rev=1.3">2005/12/04</a> +- <li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-74/srfi-74.html?rev=1.4">2005/12/15</a> ++ <li> ++ <a href="srfi-4.html">SRFI 4</a> (Homogeneous numeric ++ vector datatypes) ++ </li> ++ <li> ++ <a href="https://srfi.schemers.org/srfi-56/">SRFI 56</a> (Binary I/O) ++ </li> ++ <li> ++ <a href="srfi-66.html">SRFI 66</a> (Octet Vectors) ++ </li> + </ul> +-<h1>Abstract</h1><p>This SRFI defines a set of procedures for creating, accessing, and manipulating octet-addressed blocks of binary data, in short, <i>blobs</i>. The SRFI provides access primitives for fixed-length integers of arbitrary size, with specified endianness, and a choice of unsigned and two's complement representations.</p><h1>Rationale</h1><p>Many applications must deal with blocks of binary data by accessing them in various ways---extracting signed or unsigned numbers of various sizes. Such an application can use octet vectors as in <a href="http://srfi.schemers.org/srfi-66/">SRFI 66</a> or any of the other types of homogeneous vectors in <a href="http://srfi.schemers.org/srfi-4/">SRFI 4</a>, but these both only allow retrieving the binary data of one type.</p><p>This is awkward in many situations, because an application might access different kinds of entities from a single binary block. Even for uniform blocks, the disjointness of the various vector data types in SRFI 4 means that, say, an I/O API needs to provide an army of procedures for each of them in order to provide efficient access to binary data.</p><p>Therefore, this SRFI provides a <em>single</em> type for blocks of binary data with multiple ways to access that data. It deals only with integers in various sizes with specified endianness, because these are the most frequent applications. Dealing with other kinds of binary data, such as floating-point numbers or variable-size integers would be natural extensions, but are left for a future SRFI.</p><h1>Specification</h1><h2>General remarks</h2><p>Blobs are objects of a new type. Conceptually, a blob represents a sequence of octets.</p><p>Scheme systems implementing both SRFI 4 and/or SRFI 66 and this SRFI may or may not use the same type for u8vector and blobs. They are encouraged to do so, however.</p><p>As with u8vectors, the length of a blob is the number of octets it contains. This number is fixed. A valid index into a blob is an exact, non-negative integer. The first octet of a blob has index 0, the last octet has an index one less than the length of the blob.</p><p>Generally, the access procedures come in different flavors according to the size of the represented integer, and the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a> of the representation. The procedures also distinguish signed and unsigned representations. The signed representations all use <a href="http://en.wikipedia.org/wiki/Two's_complement">two's complement</a>.</p><p>For procedures that have no "natural" return value, this SRFI often uses the sentence</p><p><em>The return values are unspecified.</em></p><p>This means that number of return values and the return values are unspecified. However, the number of return values is such that it is accepted by a continuation created by <code>begin</code>. Specifically, on Scheme implementations where continuations created by <code>begin</code> accept an arbitrary number of arguments (this includes most implementations), it is suggested that the procedure return zero return values.</p><h2>Interface</h2><dl><dt><code>(endianness </code><code>big</code><code>)</code> (syntax)</dt><dt><code>(endianness </code><code>little</code><code>)</code> (syntax)</dt><dt><code>(endianness </code><code>native</code><code>)</code> (syntax)</dt><dd><p><code>(endianness big)</code> and <code>(endianness little)</code> evaluate to two distinct and unique objects representing an endianness. The <code>native</code> endianness evaluates to the endianness of the underlying machine architecture, and must be <code>eq?</code> to either <code>(endianness big)</code> or <code>(endianness little)</code>.</p></dd><dt><code>(blob? </code><var>obj</var><code>)</code></dt><dd><p>Returns <code>#t</code> if <var>obj</var> is a blob, otherwise returns <code>#f</code>.</p></dd><dt><code>(make-blob </code><var>k</var><code>)</code></dt><dd><p>Returns a newly allocated blob of <var>k</var> octets, all of them 0.</p></dd><dt><code>(blob-length </code><var>blob</var><code>)</code></dt><dd><p>Returns the number of octets in <var>blob</var> as an exact integer.</p></dd><dt><code>(blob-u8-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s8-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dd><p><var>K</var> must be a valid index of <var>blob</var>.</p><p><code>Blob-u8-ref</code> returns the octet at index <var>k</var> of <var>blob</var>.</p><p><code>Blob-s8-ref</code> returns the exact integer corresponding to the two's complement representation at index <var>k</var> of <var>blob</var>.</p></dd><dt><code>(blob-u8-set! </code><var>blob</var> <var>k</var> <var>octet</var><code>)</code></dt><dt><code>(blob-s8-set! </code><var>blob</var> <var>k</var> <var>byte</var><code>)</code></dt><dd><p><var>K</var> must be a valid index of <var>blob</var>.</p><p><code>Blob-u8-set!</code> stores <var>octet</var> in element <var>k</var> of <var>blob</var>.</p><p><var>Byte</var>, must be an exact integer in the interval {-128, ..., 127}. <code>Blob-u8-set!</code> stores the two's complement representation of <var>byte</var> in element <var>k</var> of <var>blob</var>.</p><p>The return values are unspecified.</p></dd><dt><code>(blob-uint-ref </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-sint-ref </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-uint-set! </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-sint-set! </code><var>size</var> <var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dd><p><var>Size</var> must be a positive exact integer. <var>K</var> must be a valid index of <var>blob</var>; so must the indices {<var>k</var>, ..., <var>k</var> + <var>size</var> - 1}. <var>Endianness</var> must be an endianness object. </p><p><code>Blob-uint-ref</code> retrieves the exact integer corresponding to the unsigned representation of size <var>size</var> and specified by <var>endianness</var> at indices {<var>k</var>, ..., <var>k</var> + <var>size</var> - 1}.</p><p><code>Blob-sint-ref</code> retrieves the exact integer corresponding to the two's complement representation of size <var>size</var> and specified by <var>endianness</var> at indices {<var>k</var>, ..., <var>k</var> + <var>size</var> - 1}.</p><p>For <code>blob-uint-set!</code>, <var>n</var> must be an exact integer in the interval [0, (256^<var>size</var>)-1]. <code>Blob-uint-set!</code> stores the unsigned representation of size <var>size</var> and specified by <var>endianness</var> into the blob at indices {<var>k</var>, ..., <var>k</var> + <var>size</var> - 1}.</p><p>For <code>blob-uint-set!</code>, <var>n</var> must be an exact integer in the interval [-256^(<var>size</var>-1), (256^(<var>size</var>-1))-1]. <code>Blob-sint-set!</code> stores the two's complement representation of size <var>size</var> and specified by <var>endianness</var> into the blob at indices {<var>k</var>, ..., <var>k</var> + <var>size</var> - 1}.</p></dd><dt><code>(blob-u16-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s16-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u16-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s16-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u16-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s16-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-u16-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s16-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dd><p><var>K</var> must be a valid index of <var>blob</var>; so must the index <var>k</var>+ 1. <var>Endianness</var> must be an endianness object. </p><p>These retrieve and set two-octet representations of numbers at indices <var>k</var> and <var>k</var>+1, according to the endianness specified by <var>endianness</var>. The procedures with <code>u16</code> in their names deal with the unsigned representation, those with <code>s16</code> with the two's complement representation.</p><p>The procedures with <code>native</code> in their names employ the native endianness, and only work at aligned indices: <var>k</var> must be a multiple of 2. It is an error to use them at non-aligned indices.</p></dd><dt><code>(blob-u32-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s32-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u32-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s32-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u32-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s32-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-u32-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s32-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dd><p><var>K</var> must be a valid index of <var>blob</var>; so must the indices {<var>k</var>, ..., <var>k</var>+ 3}. <var>Endianness</var> must be an endianness object. </p><p>These retrieve and set four-octet representations of numbers at indices {<var>k</var>, ..., <var>k</var>+ 3}, according to the endianness specified by <var>endianness</var>. The procedures with <code>u32</code> in their names deal with the unsigned representation, those with <code>s32</code> with the two's complement representation.</p><p>The procedures with <code>native</code> in their names employ the native endianness, and only work at aligned indices: <var>k</var> must be a multiple of 4. It is an error to use them at non-aligned indices.</p></dd><dt><code>(blob-u64-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s64-ref </code><var>endianness</var> <var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u64-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-s64-native-ref </code><var>blob</var> <var>k</var><code>)</code></dt><dt><code>(blob-u64-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s64-set! </code><var>endianness</var> <var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-u64-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dt><code>(blob-s64-native-set! </code><var>blob</var> <var>k</var> <var>n</var><code>)</code></dt><dd><p><var>K</var> must be a valid index of <var>blob</var>; so must the indices {<var>k</var>, ..., <var>k</var>+ 7}. <var>Endianness</var> must be an endianness object. </p><p>These retrieve and set eight-octet representations of numbers at indices {<var>k</var>, ..., <var>k</var>+ 7}, according to the endianness specified by <var>endianness</var>. The procedures with <code>u64</code> in their names deal with the unsigned representation, those with <code>s64</code> with the two's complement representation.</p><p>The procedures with <code>native</code> in their names employ the native endianness, and only work at aligned indices: <var>k</var> must be a multiple of 8. It is an error to use them at non-aligned indices.</p></dd><dt><code>(blob=? </code><var>blob-1</var> <var>blob-2</var><code>)</code></dt><dd><p>Returns <var>#t</var> if <var>blob-1</var> and <var>blob-2</var> are equal---that is, if they have the same length and equal octets at all valid indices.</p></dd><dt><code>(blob-copy! </code><var>source</var> <var>source-start</var> <var>target</var> <var>target-start</var> <var>n</var><code>)</code></dt><dd><p>Copies data from blob <var>source</var> to blob <var>target</var>. <var>Source-start</var>, <var>target-start</var>, and <var>n</var> must be non-negative exact integers that satisfy</p><p>0 <= <var>source-start</var> <= <var>source-start</var> + <var>n</var> <= <code>(blob-length <var>source</var>)</code></p><p>0 <= <var>target-start</var> <= <var>target-start</var> + <var>n</var> <= <code>(blob-length <var>target</var>)</code></p><p>This copies the octets from <var>source</var> at indices [<var>source-start</var>, <var>source-start</var> + <var>n</var>) to consecutive indices in <var>target</var> starting at <var>target-index</var>.</p><p>This must work even if the memory regions for the source and the target overlap, i.e., the octets at the target location after the copy must be equal to the octets at the source location before the copy.</p><p>The return values are unspecified.</p></dd><dt><code>(blob-copy </code><var>blob</var><code>)</code></dt><dd><p>Returns a newly allocated copy of blob <var>blob</var>.</p></dd><dt><code>(blob->u8-list </code><var>blob</var><code>)</code></dt><dt><code>(u8-list->blob </code><var>blob</var><code>)</code></dt><dd><p><code>blob->u8-list</code>returns a newly allocated list of the octets of <var>blob</var> in the same order.</p></dd><dd><p><code>U8-list->blob</code> returns a newly allocated blob whose elements are the elements of list <var>octets</var>, which must all be octets, in the same order. Analogous to <code>list->vector</code>.</p></dd><dt><code>(blob->uint-list </code><var>size</var> <var>endianness</var> <var>blob</var><code>)</code></dt><dt><code>(blob->sint-list </code><var>size</var> <var>endianness</var> <var>blob</var><code>)</code></dt><dt><code>(uint-list->blob </code><var>size</var> <var>endianness</var> <var>list</var><code>)</code></dt><dt><code>(sint-list->blob </code><var>size</var> <var>endianness</var> <var>list</var><code>)</code></dt><dd><p><var>Size</var> must be a positive exact integer. <var>Endianness</var> must be an endianness object.</p><p>These convert between lists of integers and their consecutive representations according to <var>size</var> and <var>endianness</var> in blobs in the same way as <code>blob->u8-list</code>, <code>blob->s8-list</code>, <code> u8-list->blob</code>, and <code>s8-list->blob</code> do for one-octet representations.</p></dd></dl><h1>Reference Implementation</h1><p>This <a href="blob.scm">reference implementation</a> makes use of <a href="http://srfi.schemers.org/srfi-23/">SRFI 23</a> (Error reporting mechanism), <a href="http://srfi.schemers.org/srfi-26/">SRFI 26</a> (Notation for Specializing Parameters without Currying), <a href="http://srfi.schemers.org/srfi-60/">SRFI 60</a> (Integers as Bits), and <a href="http://srfi.schemers.org/srfi-66">SRFI 66</a> (Octet Vectors) .</p><h1>Examples</h1><p>The <a href="example.scm">test suite</a> doubles as a source of examples.</p><h1>References</h1><ul><li><a href="http://srfi.schemers.org/srfi-4/">SRFI 4</a> (Homogeneous numeric vector datatypes)</li><li><a href="http://srfi.schemers.org/srfi-56/">SRFI 56</a> (Binary I/O)</li><li><a href="http://srfi.schemers.org/srfi-66/">SRFI 66</a> (Octet Vectors)</li></ul></body><H1>Copyright</H1> +-Copyright (C) Michael Sperber (2005). All Rights Reserved. +-<p> +-Permission is hereby granted, free of charge, to any person obtaining a +-copy of this software and associated documentation files (the "Software"), +-to deal in the Software without restriction, including without limitation +-the rights to use, copy, modify, merge, publish, distribute, sublicense, +-and/or sell copies of the Software, and to permit persons to whom the +-Software is furnished to do so, subject to the following conditions: +-<p> +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +-<p> +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +-DEALINGS IN THE SOFTWARE. +- +- <hr> +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">David Van Horn</a></address> +-</body></html> ++<h2>Copyright</h2> ++<p> ++ Copyright (C) Michael Sperber (2005). All Rights Reserved. ++</p> ++<p> ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to ++ deal in the Software without restriction, including without limitation the ++ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ sell copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++</p> ++<p> ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++</p> ++<p> ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ IN THE SOFTWARE. ++</p> ++<hr /> ++<address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">David Van Horn</a></address> ++</body> ++</html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html +index 4267157..270196e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-78.html +@@ -1,102 +1,122 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd"> +-<html> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-78 ┃ ++┃ Commit: 9ecbd245bea4155da33d5fad2b94548796261dc9 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 78: Lightweight testing</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> +- +-Lightweight testing +- +-<H1>Author</H1> +- +-Sebastian Egner +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <A +-HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +- +-To provide input on this SRFI, please <code><A +-HREF="mailto:srfi-78@srfi.schemers.org">mail to +-<srfi-78@srfi.schemers.org></A></code>. See <A +-HREF=../srfi-list-subscribe.html>instructions here</A> to subscribe to +-the list. You can access previous messages via <A +-HREF=mail-archive/maillist.html>the archive of the mailing list</A>. +- +- +-<P><UL> +-<LI>Received: 2005/10/25</LI> +-<LI>Draft: 2005/11/11 - 2006/01/10</LI> +-<LI>Draft extended: 2006/01/17 - 2006/01/31</LI> +-<LI>Revised: 2006/01/18</LI> +-<LI>Revised: 2006/02/08</LI> +-<LI>Final: 2006/03/06</LI> +-</UL> +- +-<H1>Abstract</H1> +- ++<h1>SRFI 78: Lightweight testing</h1> ++ ++<p>by Sebastian Egner</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 78 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-78/srfi-78.html">https://srfi.schemers.org/srfi-78/srfi-78.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+78+at+srfi+dotschemers+dot+org">srfi-78@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-78">archive</a>.</p> ++<ul> ++<li>Received: 2005-10-25</li> ++<li>Draft: 2005-11-11--2006-01-10</li> ++<li>Draft extended: 2006-01-17--2006-01-31</li> ++<li>Revised: 2006-01-18</li> ++<li>Revised: 2006-02-08</li> ++<li>Final: 2006-03-06</li> ++<li>Revised to fix errata:<ul> ++ <li>2019-10-25 (Fix broken links.)</li></ul></li> ++</ul> ++ ++<h2>Abstract</h2> ++<p> + A simple mechanism is defined for testing Scheme programs. + As a most primitive example, the expression +- +-<PRE> (check (+ 1 1) => 3) +-</PRE> +- +-evaluates the expression <CODE>(+ 1 1)</CODE> and compares the result ++</p> ++<pre> ++ (check (+ 1 1) => 3) ++</pre> ++<p> ++evaluates the expression <code>(+ 1 1)</code> and compares the result + with the expected result 3 provided after the syntactic +-keyword <CODE>=></CODE>. Then the outcome of this comparison is reported ++keyword <code>=></code>. Then the outcome of this comparison is reported + in human-readable form by printing a message of the form +- +-<PRE> (+ 1 1) => 2 ; *** failed *** ++</p> ++<pre> ++ (+ 1 1) => 2 ; *** failed *** + ; expected result: 3 +-</PRE> +- ++</pre> ++<p> + Moreover, the outcome of any executed check is recorded + in a global state counting the number of correct and failed + checks and storing the first failed check. At the end of a + file, or at any other point, the user can print a summary +-using <CODE>check-report</CODE>. ++using <code>check-report</code>. ++</p> + <p> + In addition to the simple test above, it is also possible + to execute a parametric sequence of checks. Syntactically, + this takes the form of an eager comprehension in the sense +-of <A HREF="http://srfi.schemers.org/srfi-42">SRFI 42</A> [5]. For example, +- +-<PRE> (check-ec (:range e 100) ++of <a href="srfi-42.html">SRFI 42</a> [5]. For example, ++</p> ++<pre> ++ (check-ec (:range e 100) + (:let x (expt 2.0 e)) +- (= (+ x 1) x) => #f (e x)) +-</PRE> +- +-This statement runs the variable <CODE>e</CODE> through {0..99} and +-for each binding defines <CODE>x</CODE> as <CODE>(expt 2.0 e)</CODE>. Then it is +-checked if <CODE>(+ x 1)</CODE> is equal to <CODE>x</CODE>, and it is expected that +-this is not the case (i.e. expected value is <CODE>#f</CODE>). The +-trailing <CODE>(e x)</CODE> tells the reporting mechanism to print +-the values of both <CODE>e</CODE> and <CODE>x</CODE> in case of a failed check. ++ (= (+ x 1) x) => #f (e x)) ++</pre> ++<p> ++This statement runs the variable <code>e</code> through {0..99} and ++for each binding defines <code>x</code> as <code>(expt 2.0 e)</code>. Then it is ++checked if <code>(+ x 1)</code> is equal to <code>x</code>, and it is expected that ++this is not the case (i.e. expected value is <code>#f</code>). The ++trailing <code>(e x)</code> tells the reporting mechanism to print ++the values of both <code>e</code> and <code>x</code> in case of a failed check. + The output could look like this: +- +-<PRE> (let ((e 53) (x 9007199254740992.0)) (= (+ x 1) x)) => #t ; *** failed *** ++</p> ++<pre> ++ (let ((e 53) (x 9007199254740992.0)) (= (+ x 1) x)) => #t ; *** failed *** + ; expected result: #f +-</PRE> +- +-The specification of bindings to report, <CODE>(e x)</CODE> in the ++</pre> ++<p> ++The specification of bindings to report, <code>(e x)</code> in the + example, is optional but very informative. +- ++</p> ++<p> + Other features of this SRFI are: +-<UL> +-<LI>A way to specify a different equality predicate (default is <CODE>equal?</CODE>).</LI> +-<LI>Controlling the amount of reporting being printed.</LI> +-<LI>Switching off the execution and reporting of checks entriely.</LI> +-<LI>Retrieving a boolean if all checks have been executed and passed.</LI> +-</UL> +- +-<H1>Rationale</H1> ++</p> ++<ul> ++<li>A way to specify a different equality predicate (default is <code>equal?</code>).</li> ++<li>Controlling the amount of reporting being printed.</li> ++<li>Switching off the execution and reporting of checks entriely.</li> ++<li>Retrieving a boolean if all checks have been executed and passed.</li> ++</ul> ++ ++<h2>Rationale</h2> ++<p> + The mechanism defined in this SRFI should be available in + every Scheme system because it has already proven useful + for interactive development---of SRFIs. ++</p> + <p> + Although it is extremely straight-forward, the origin of the + particular mechanism described here is the 'examples.scm' file +@@ -104,209 +124,234 @@ accompanying the reference implementation of SRFI 42 [5]. + The same mechanism has been reimplemented for the reference + implementation of SRFI 67, and a simplified version is yet + again found in the reference implementation of SRFI 77. ++</p> + <p> + The mechanism in this SRFI does not replace more sophisticated + approaches to unit testing, like SRFI 64 [1] or SchemeUnit [2]. + These systems provide more control of the testing, separate + the definition of a test, its execution, and its reports, and + provide several other features. ++</p> + <p> + Neil Van Dyke's Testeez library [3] is very close in spirit + to this SRFI. In Testeez, tests are disabled by (re-)defining a + macro. The advantage of this method is that the code for the + test cases can be removed entirely, and hence even the dependency + on the Testeez library. This SRFI on the other hand, uses a +-Scheme conditional (<CODE>COND</CODE>, <CODE>IF</CODE>) to prevent execution of the ++Scheme conditional (<code>COND</code>, <code>IF</code>) to prevent execution of the + testing code. This method is more dynamic but retains dead + testing code, unless a compiler and a module system are used + to apply constant folding and dead code elimination. The only + major addition in SRFI over Testeez is the comprehension for + formulating parametric tests. ++</p> + <p> + Design considerations for this SRFI include the following: +-<UL> +-<LI> Reporting is human-readable and as specific as possible, ++</p> ++<ul> ++<li> Reporting is human-readable and as specific as possible, + i.e. not just "assertion failed" but the expression with + actual and expected value, and if possibly the relevant +- part of the bindings environment.</LI> +-<LI> An effort is made to print closed Scheme expressions, i.e. ++ part of the bindings environment.</li> ++<li> An effort is made to print closed Scheme expressions, i.e. + expressions that can directly be copy/pasted into a REPL +- for further analysis (e.g. the let expression in the abstract).</LI> +-<LI> By default the checks report both correct and failed checks. ++ for further analysis (e.g. the let expression in the abstract).</li> ++<li> By default the checks report both correct and failed checks. + However, it is possible to reduce the output---or even to + switch off the execution of checks. It has turned out useful + to be able to run only some subset checks for the features + currently under development. This can be done by changing +- the reporting mode between different sections.</LI> +-<LI> The global state (correct/failed count) is not made available ++ the reporting mode between differnt sections.</li> ++<li> The global state (correct/failed count) is not made available + to the user program. This reduces the dependencies between +- different checks because it is not possible to use the state.</LI> +-<LI> Ocassionally, it is useful to check that a certain expression +- does <I>not</I> yield an ordinary result but raises an error. However, ++ different checks because it is not possible to use the state.</li> ++<li> Ocassionally, it is useful to check that a certain expression ++ does <i>not</i> yield an ordinary result but raises an error. However, + R5RS [4] does not specify the mechanism by which this occurs + (e.g. raising exception, breaking into a REPL, aborting the + program, etc.). For this reason, this SRFI is restricted to +- the case that the checked expressions evaluate normally.</LI> +-<LI> Though usually I am very much in favor of strictly prefix ++ the case that the checked expressions evaluate normally.</li> ++<li> Though usually I am very much in favor of strictly prefix + syntax, for this SRFI I make an exception because the +- infix "<CODE>=></CODE>" syntax is widely used and intuitive.</LI> +-</UL> ++ infix "<code>=></code>" syntax is widely used and intuitive.</li> ++</ul> + +-<H1>Specification</H1> ++<h2>Specification</h2> + +-<DL> +-<DT><CODE> +-(<a name="check">check</a> <expr> (=> <equal>) <expected>) </CODE> MACRO<CODE><BR> ++<dl> ++<dt id="check"><code> ++(check <expr> (=> <equal>) <expected>) </code> MACRO<code><br /> + (check <expr> => <expected>) +-</CODE></DT> +-<DD> +- evaluates <CODE><expr></CODE> and compares the value to the value +- of <CODE><expected></CODE> using the predicate <CODE><equal></CODE>, which is +- <CODE>equal?</CODE> when omitted. Then a report is printed according ++</code></dt> ++<dd> ++ evaluates <code><expr></code> and compares the value to the value ++ of <code><expected></code> using the predicate <code><equal></code>, which is ++ <code>equal?</code> when omitted. Then a report is printed according + to the current mode setting (see below) and the outcome +- is recorded in a global state to be used in <CODE>check-report</CODE>. +- The precise order of evaluation is that first <CODE><equal></CODE> +- and <CODE><expected></CODE> are evaluated (in unspecified order) and +- then <CODE><expr></CODE> is evaluated.<BR> +- Example: <CODE>(check (+ 1 1) => 2)</CODE> +-</DD> +-</DL> +- +-<DL> +-<DT><CODE> +-(<a name="check-ec">check-ec</a> <qualifier></CODE>*<CODE> <expr> (=> <equal>) <expected> (<argument></CODE>*<CODE>)) </CODE> MACRO<CODE><BR> +-(check-ec <qualifier></CODE>*<CODE> <expr> => <expected> (<argument></CODE>*<CODE>))<BR> +-(check-ec <qualifier></CODE>*<CODE> <expr> (=> <equal>) <expected>)<BR> +-(check-ec <qualifier></CODE>*<CODE> <expr> => <expected>) +-</CODE></DT> +-<DD> +- an eager comprehension for executing a parametric sequence of checks.<p> +- Enumerates the sequence of bindings specified by <CODE><qualifier></CODE>*. +- For each binding evaluates <CODE><equal></CODE> and <CODE><expected></CODE> in unspecified +- order. Then evalues <CODE><expr></CODE> and compares the value obtained to the +- value of <CODE><expected></CODE> using the value of <CODE><equal></CODE> as predicate, which +- is <CODE>equal?</CODE> when omitted. ++ is recorded in a global state to be used in <code>check-report</code>. ++ The precise order of evaluation is that first <code><equal></code> ++ and <code><expected></code> are evaluated (in unspecified order) and ++ then <code><expr></code> is evaluated.<br /> ++ Example: <code>(check (+ 1 1) => 2)</code> ++</dd> ++</dl> ++ ++<dl> ++<dt id="check-ec"><code> ++(check-ec <qualifier></code>*<code> <expr> (=> <equal>) <expected> (<argument></code>*<code>)) </code> MACRO<code><br /> ++(check-ec <qualifier></code>*<code> <expr> => <expected> (<argument></code>*<code>))<br /> ++(check-ec <qualifier></code>*<code> <expr> (=> <equal>) <expected>)<br /> ++(check-ec <qualifier></code>*<code> <expr> => <expected>) ++</code></dt> ++<dd> ++<p> ++ an eager comprehension for executing a parametric sequence of checks. ++</p> ++<p> ++ Enumerates the sequence of bindings specified by <code><qualifier></code>*. ++ For each binding evaluates <code><equal></code> and <code><expected></code> in unspecified ++ order. Then evalues <code><expr></code> and compares the value obtained to the ++ value of <code><expected></code> using the value of <code><equal></code> as predicate, which ++ is <code>equal?</code> when omitted. + The comprehension stops after the first failed check, if there + is any. Then a report is printed according to the current mode + setting (see below) and the outcome is recorded in a global state +- to be used in <CODE>check-report</CODE>. The entire <CODE>check-ec</CODE> counts as a single +- check.<P> +- In case the check fails <CODE><argument></CODE>* is used for constructing an +- informative message with the argument values. Use <CODE><argument></CODE>* to +- list the relevant free variables of <CODE><expr></CODE> (see examples) that you +- want to have printed.<P> +- A <CODE><qualifier></CODE> is any qualifier of an eager comprehension as +- specified in <A HREF="http://srfi.schemers.org/srfi-42">SRFI 42</A> [5].<P> +- ++ to be used in <code>check-report</code>. The entire <code>check-ec</code> counts as a single ++ check.</p><p> ++ In case the check fails <code><argument></code>* is used for constructing an ++ informative message with the argument values. Use <code><argument></code>* to ++ list the relevant free variables of <code><expr></code> (see examples) that you ++ want to have printed.</p><p> ++ A <code><qualifier></code> is any qualifier of an eager comprehension as ++ specified in <a href="srfi-42.html">SRFI 42</a> [5]. ++</p> ++<p> + Examples: +- <PRE> (check-ec (: e 100) (positive? (expt 2 e)) => #t (e)) ; fails on fixnums ++</p> ++ <pre> ++ (check-ec (: e 100) (positive? (expt 2 e)) => #t (e)) ; fails on fixnums + (check-ec (: e 100) (:let x (expt 2.0 e)) (= (+ x 1) x) => #f (x)) ; fails + (check-ec (: x 10) (: y 10) (: z 10) + (* x (+ y z)) => (+ (* x y) (* x z)) + (x y z)) ; passes with 10^3 cases checked +- </PRE> +-</DD> +-</DL> ++ </pre> ++</dd> ++</dl> ++ + +-<DL> +-<DT><CODE> +-(<a name="check-report">check-report</a>) </CODE> PROCEDURE<CODE> +-</CODE></DT> +-<DD> ++<dl> ++<dt id="check-report"><code> ++(check-report) </code> PROCEDURE<code> ++</code></dt> ++<dd> ++<p> + prints a summary and the first failed check, if there is any, + depending on the current mode settings. +-</DD> +-</DL> +- +-<DL> +-<DT><CODE> +-(<a name="check-set-mode">check-set-mode!</a> mode) </CODE> PROCEDURE<CODE> +-</CODE></DT> +-<DD> ++</p> ++</dd> ++</dl> ++ ++<dl> ++<dt id="check-set-mode"><code> ++(check-set-mode! mode) </code> PROCEDURE<code> ++</code></dt> ++<dd> ++<p> + sets the current mode to mode, which must be a symbol in +- <CODE>'(off summary report-failed report)</CODE>, default is <CODE>'report</CODE>. ++ <code>'(off summary report-failed report)</code>, default is <code>'report</code>. + Note that you can change the mode at any time, and that check, +- <CODE>check-ec</CODE> and <CODE>check-report</CODE> use the current value. +-<P> +- The mode symbols have the following meaning:<BR> +- <CODE>off</CODE>: do not execute any of the checks,<BR> +- <CODE>summary</CODE>: print only summary in <CODE>(check-report)</CODE> and nothing else,<BR> +- <CODE>report-failed</CODE>: report failed checks when they happen, and in summary,<BR> +- <CODE>report</CODE>: report every example executed.<BR> +-</DD> +-</DL> +- +-<DL> +-<DT><CODE> +-(<a name="check-reset">check-reset!</a>) </CODE> PROCEDURE<CODE> +-</CODE></DT> +-<DD> ++ <code>check-ec</code> and <code>check-report</code> use the current value. ++</p> ++<p> ++ The mode symbols have the following meaning:<br /> ++ <code>off</code>: do not execute any of the checks,<br /> ++ <code>summary</code>: print only summary in <code>(check-report)</code> and nothing else,<br /> ++ <code>report-failed</code>: report failed checks when they happen, and in summary,<br /> ++ <code>report</code>: report every example executed.<br /> ++</p> ++</dd> ++</dl> ++ ++ ++<dl> ++<dt id="check-reset"><code> ++(check-reset!) </code> PROCEDURE<code> ++</code></dt> ++<dd> + resets the global state (counters of correct/failed examples) + to the state immediately after loading the module for the + first time, i.e. no checks have been executed. +-</DD> +-</DL> +- +-<DL> +-<DT><CODE> +-(<a name="check-passed">check-passed?</a> expected-total-count) </CODE> PROCEDURE<CODE> +-</CODE></DT> +-<DD> +- <CODE>#t</CODE> if there were no failed checks and expected-total-count +- correct checks, <CODE>#f</CODE> otherwise.<P> ++</dd> ++</dl> ++ ++<dl> ++<dt id="check-passed"><code> ++(check-passed? expected-total-count) </code> PROCEDURE<code> ++</code></dt> ++<dd> ++<p> ++ <code>#t</code> if there were no failed checks and expected-total-count ++ correct checks, <code>#f</code> otherwise. ++</p> ++<p> + Rationale: This procedure can be used in automatized + tests by terminating a test program with the statement +- <CODE>(exit (if (check-passed? </CODE><I>n</I><CODE>) 0 1))</CODE>. +-</DD> +-</DL> +- ++ <code>(exit (if (check-passed? </code><i>n</i><code>) 0 1))</code>. ++</p> ++</dd> ++</dl> + +-<H1>Implementation</H1> + +-<A HREF="check.scm">check.scm</A>: ++<h2>Implementation</h2> ++<p> ++<a href="https://srfi.schemers.org/srfi-78/check.scm">check.scm</a>: + implementation in R5RS + SRFI 23 (error) + SRFI 42 (comprehensions); +- tested under PLT 208p1 and Scheme 48 1.3.<br> +- +-<A HREF="examples.scm">examples.scm</A>: ++ tested under PLT 208p1 and Scheme 48 1.3.<br /> ++</p> ++<p> ++<a href="https://srfi.schemers.org/srfi-78/examples.scm">examples.scm</a>: + a few examples. ++</p> ++<h2>References</h2> + +-<H1>References</H1> +- +-<UL> +-<LI><A NAME="1">[1]</A> ++<ul> ++<li><a name="1">[1]</a> + SRFI 64 by Per Bothner: A Scheme API for test suites. January 2005. +- <A HREF="http://srfi.schemers.org/srfi-64">http://srfi.schemers.org/srfi-64</A></LI> ++ <a href="srfi-64.html">http://srfi.schemers.org/srfi-64</a></li> + +-<LI><A NAME="2">[2]</A> ++<li><a name="2">[2]</a> + Noel Welsh: SchemeUnit. February 2003. +- <A HREF="http://schematics.sourceforge.net/schemeunit.html">http://schematics.sourceforge.net/schemeunit.html</A></LI> ++ <a href="https://pkgs.racket-lang.org/package/schemeunit">https://pkgs.racket-lang.org/package/schemeunit</a></li> + +-<LI><A NAME="3">[3]</A> ++<li><a name="3">[3]</a> + Neil Van Dyke: + Testeez, Lightweight Unit Test Mechanism for Scheme. May 2005. +- <A HREF="http://www.neilvandyke.org/testeez">http://www.neilvandyke.org/testeez</A></LI> ++ <a href="http://www.neilvandyke.org/testeez">http://www.neilvandyke.org/testeez</a></li> + +-<LI><A NAME="4">[4]</A> ++<li><a name="4">[4]</a> + Revised^5 Report on the Algorithmic Language Scheme (R5RS). +- <A HREF="http://www.schemers.org/Documents/Standards/R5RS/">http://www.schemers.org/Documents/Standards/R5RS/</A></LI> ++ <a href="http://www.schemers.org/Documents/Standards/R5RS/">http://www.schemers.org/Documents/Standards/R5RS/</a></li> + +-<LI><A NAME="5">[5]</A> ++<li><a name="5">[5]</a> + SRFI 42 by Sebastian Egner: Eager Comprehensions. +- <A HREF="http://srfi.schemers.org/srfi-42">http://srfi.schemers.org/srfi-42</A></LI> +-</UL> +- +-<H1>Copyright</H1> ++ <a href="srfi-42.html">http://srfi.schemers.org/srfi-42</a></li> ++</ul> + ++<h2>Copyright</h2> ++<p> + Copyright (C) Sebastian Egner (2005-2006). All Rights Reserved. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: ++</p> + <p> + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ++</p> + <p> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-<p> +- <hr> ++</p> ++ <hr /> + <address>Author: <a href="mailto:srfi-78@sebastian-egner.net">srfi-78@sebastian-egner.net</a></address> +- <address>Editors: <a href="mailto:srfi-editors@srfi.schemers.org">srfi-editors@srfi.schemers.org</a></address> +- </body> ++ <address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">David Van Horn</a></address> ++</body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html +index 38b7340..ed3e26e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-8.html +@@ -1,41 +1,58 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 3.2//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> + <head> +-<title>SRFI 8: RECEIVE: Binding to multiple values</title> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-8 ┃ ++┃ Commit: d739b8954139f7a4a9bb4ae70a23600584084035 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 8: RECEIVE: Binding to multiple values</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> +-<H1>Title</H1> ++<h1>SRFI 8: <code>receive</code>: Binding to multiple values</h1> + +-SRFI 8: <code>receive</code>: Binding to multiple values +- +-<H1>Author</H1> +- +-John David Stone +- +-<p> ++<p>by John David Stone<br /> + Department of Mathematics and Computer Science, Grinnell College, Grinnell, Iowa 50112, + <a href="mailto:stone@cs.grinnell.edu">email</a>. + </p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 8 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-8/srfi-8.html">https://srfi.schemers.org/srfi-8/srfi-8.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Status</H1> ++<h2>Status</h2> + +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-8/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/05/27 +-<LI>Draft: 1999/07/01-1999/08/30 +-<LI>Final: 1999/08/30 +-</UL> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+8+at+srfi+dotschemers+dot+org">srfi-8@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-8">archive</a>.</p> ++<ul> ++<li>Received: 1999-05-27 ++</li><li>Draft: 1999-07-01--1999-08-30 ++</li><li>Final: 1999-08-30 ++</li></ul> + +-<H1>Related SRFIs</H1> ++<h2>Related SRFIs</h2> + + <p> + The syntax proposed in this SRFI is used in the reference implementation of + <a href="srfi-1.html">SRFI-1</a>, ``List library.'' + </p> + +-<H1>Abstract</H1> ++<h2>Abstract</h2> + + <p> + The only mechanism that R<sup>5</sup>RS provides for binding identifiers to +@@ -44,7 +61,7 @@ the values of a multiple-valued expression is the primitive + readable syntax for creating such bindings. + </p> + +-<H1>Rationale</H1> ++<h2>Rationale</h2> + + <p> + Although R<sup>5</sup>RS supports multiple-valued expressions, it provides +@@ -116,8 +133,8 @@ established from a ``body'' in which they are used makes it easier to + follow the code. + </p> + +-<H1>Specification</H1> +-<a name="receive"></a> ++<h2 id="receive">Specification</h2> ++ + <p> + <code>(receive</code> <formals> <expression> + <body><code>)</code> library syntax +@@ -134,7 +151,7 @@ forms: + <code>(</code><variable<sub>1</sub>> <code>...</code> + <variable<sub><i>n</i></sub>><code>)</code>: The environment in which + the <code>receive</code>-expression is evaluated is extended by binding +-</code><variable<sub>1</sub>>, ..., ++<variable<sub>1</sub>>, ..., + <variable<sub><i>n</i></sub>> to fresh locations. The + <expression> is evaluated, and its values are stored into those + locations. (It is an error if <expression> does not have exactly +@@ -154,7 +171,7 @@ stored in the location bound to <variable>. + <variable<sub><i>n</i></sub>> . <variable<sub><i>n</i> + + 1</sub>><code>)</code>: The environment in which + the <code>receive</code>-expression is evaluated is extended by binding +-</code><variable<sub>1</sub>>, ..., ++<variable<sub>1</sub>>, ..., + <variable<sub><i>n</i> + 1</sub>> to fresh locations. The + <expression> is evaluated. Its first <i>n</i> values are stored into + the locations bound to <variable<sub>1</sub>> <code>...</code> +@@ -172,7 +189,7 @@ the extended environment. The results of the last expression in the body + are the values of the <code>receive</code>-expression. + </p> + +-<H1>Reference implementation</H1> ++<h2>Reference implementation</h2> + + <pre> + <code> +@@ -184,7 +201,7 @@ are the values of the <code>receive</code>-expression. + </code> + </pre> + +-<hr> ++<hr /> + + <p> + Copyright (C) John David Stone (1999). All Rights Reserved. +@@ -213,9 +230,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +-<hr> ++<hr /> + +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html +index 39255f2..414fc56 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-86.html +@@ -1,41 +1,51 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +-<html><head><title>SRFI 86: MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET-syntax</title></head><body> +- +-<h1>Title</h1> +- +-MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET-syntax +- +-<h1>Author</h1> +- +-Joo ChurlSoo +- +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a href="http://srfi.schemers.org/srfi%20minus%20process.html">here</a>. +-To +-provide input on this SRFI, please <code> +-<a href="mailto:srfi-86%20at%20srfi%20dot%20schemers%20dot%20org">mailto:srfi minus 86 at srfi dot schemers dot org</a></code>. +-See <a href="http://srfi.schemers.org/srfi%20minus%20list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access the discussion via +-<a href="http://srfi.schemers.org/srfi-86/mail-archive/maillist.html">the +-archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-86/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-<p> +-</p><ul> +- <li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-86/srfi-86.txt?rev=1.1">2006/04/03</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-86/srfi-86.txt?rev=1.2">2006/05/08</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-86/srfi-86.txt?rev=1.3">2006/05/22</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-86/srfi-86.txt?rev=1.4">2006/06/20</a></li> +- <li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-86/srfi-86.html?rev=1.7">2006/06/20</a></li> +- <li>Draft: 2006/04/04 - 2006/06/01</li> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN" "http://www.w3.org/TR/html.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-86 ┃ ++┃ Commit: 9ec9241973865d0d07f70a4462775111d7c82721 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 86: MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET-syntax</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> ++ <body> ++ ++<h1>SRFI 86: MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET-syntax</h1> ++ ++<p>by Joo ChurlSoo</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 86 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-86/srfi-86.html">https://srfi.schemers.org/srfi-86/srfi-86.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+86+at+srfi+dotschemers+dot+org">srfi-86@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-86">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-86/srfi-86-1.1.txt">2006-04-03</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-86/srfi-86-1.2.txt">2006-05-08</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-86/srfi-86-1.3.txt">2006-05-22</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-86/srfi-86-1.4.txt">2006-06-20</a></li> ++ <li>Final: <a href="https://srfi.schemers.org/srfi-86/srfi-86-1.7.html">2006-06-20</a></li> ++ <li>Draft: 2006-04-04--2006-06-01</li> + </ul> + +-<h1>Abstract</h1> ++<h2>Abstract</h2> + + <p> + Unlike the <code>values</code>/<code>call-with-values</code> mechanism of +@@ -66,7 +76,7 @@ multiple values. In addition, they have several new binding forms for + useful functions such as escape, recursion, etc. + </p> + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + + <p> + It is impossible to bind the evaluated result of <code>values</code> +@@ -79,7 +89,8 @@ consumer procedure of <code>call-with-values</code>. The following are examples + show the differences. + </p> + +-<pre>(define v (values 1 2 3)) => error ++<pre> ++(define v (values 1 2 3)) => error + (define v (lambda () (values 1 2 3))) => (lambda () (values 1 2 3)) + (define m (mu 1 2 3)) => (lambda (f) (f 1 2 3)) + (define a (apply values 1 '(2 3))) => error +@@ -107,21 +118,24 @@ best explained by simple examples. + + <p>In <a href="#SRFI11">SRFI 11</a>:</p> + +-<pre>(let-values ((a (values 1 2)) ((b c) (values 3 4))) ++<pre> ++(let-values ((a (values 1 2)) ((b c) (values 3 4))) + (list a b c)) + => ((1 2) 3 4) + </pre> + + <p>In <a href="#SRFI71">SRFI 71</a>:</p> + +-<pre>(srfi-let (((values . a) (values 1 2)) ((values b c) (values 3 4))) ++<pre> ++(srfi-let (((values . a) (values 1 2)) ((values b c) (values 3 4))) + (list a b c)) + => ((1 2) 3 4) + </pre> + + <p>In this SRFI:</p> + +-<pre>(alet (a (mu 1 2) ((b c) (mu 3 4))) ++<pre> ++(alet (a (mu 1 2) ((b c) (mu 3 4))) + (list a b c)) + => ((1 2) 3 4) + </pre> +@@ -134,7 +148,8 @@ sequence from left to right unlike <code>let</code> of R5RS and + + <p>In <a href="#SRFI71">SRFI 71</a>:</p> + +-<pre>(srfi-let ((a (begin (display "1st") 1)) ++<pre> ++(srfi-let ((a (begin (display "1st") 1)) + (b c (values (begin (display "2nd") 2) 3)) + (d (begin (display "3rd") 4)) + ((values e . f) (values (begin (display "4th") 5) 6))) +@@ -144,7 +159,8 @@ sequence from left to right unlike <code>let</code> of R5RS and + + <p>In this SRFI:</p> + +-<pre>(alet ((a (begin (display "1st") 1)) ++<pre> ++(alet ((a (begin (display "1st") 1)) + (b c (mu (begin (display "2nd") 2) 3)) + (d (begin (display "3rd") 4)) + ((e . f) (mu (begin (display "4th") 5) 6))) +@@ -157,7 +173,8 @@ sequence from left to right unlike <code>let</code> of R5RS and + syntactically possible, as well as a single expression that produce + multiple values.</p> + +-<pre>(alet* (((a b) (mu 1 2)) ++<pre> ++(alet* (((a b) (mu 1 2)) + ((c d e) a (+ a b c) (+ a b c d)) + ((f . g) (mu 5 6 7)) + ((h i j . k) e 9 10 h i j)) +@@ -172,14 +189,16 @@ allowed to take multiple values bindings.</p> + + <p>In <a href="#SRFI71">SRFI 71</a>:</p> + +-<pre>(srfi-let tag ((a 1) (b 2) (c 3) (d 4) (e 5)) ++<pre> ++(srfi-let tag ((a 1) (b 2) (c 3) (d 4) (e 5)) + (if (< a 10) (tag 10 b c d e) (list a b c d e))) + => (10 2 3 4 5) + </pre> + + <p>In this SRFI:</p> + +-<pre>(alet* tag ((a 1) (a b b c (mu (+ a 2) 4 5 6)) ((d e e) b 5 (+ a b c))) ++<pre> ++(alet* tag ((a 1) (a b b c (mu (+ a 2) 4 5 6)) ((d e e) b 5 (+ a b c))) + (if (< a 10) (tag a 10 b c c d e d) (list a b c d e))) + => (10 6 6 5 5) + </pre> +@@ -189,7 +208,8 @@ allowed to take multiple values bindings.</p> + named-<code>alet</code>. It is also allowed to take multiple values + bindings.</p> + +-<pre>(alet* ((a 1) ++<pre> ++(alet* ((a 1) + ((b 2) (b c c (mu 3 4 5)) ((d e d (mu a b c)) . intag) . tag) + (f 6)) + (if (< d 10) +@@ -203,7 +223,8 @@ bindings.</p> + + <li><p>They have a new binding form that has an escape function.</p> + +-<pre>(alet ((exit) ++<pre> ++(alet ((exit) + (a (begin (display "1st") 1)) + (b c (mu (begin (display "2nd") 2) (begin (display "3rd") 3)))) + (display (list a b c)) +@@ -217,7 +238,8 @@ bindings.</p> + integrated into the <code>alet</code> and <code>alet*</code> with a + syntactic keyword <code>and</code>.</p> + +-<pre>(alet ((and (a (begin (display "1st") 1)) ++<pre> ++(alet ((and (a (begin (display "1st") 1)) + (b (begin (display "2nd") 2)) + (c (begin (display "false") #f)) + (d (begin (display "3nd") 3)))) +@@ -238,7 +260,8 @@ integrated into the <code>alet</code> and <code>alet*</code> with a + syntactic keywords <code>opt</code> and <code>cat</code> in the + similar way to <code>let-optionals</code> in Scsh.</p> + +-<pre>((lambda (str . rest) ++<pre> ++((lambda (str . rest) + (alet* ((len (string-length str)) + (opt rest + (start 0 (integer? start) +@@ -277,8 +300,9 @@ integrated into the <code>alet</code> and <code>alet*</code> with a + are integrated into the <code>alet</code> and + <code>alet*</code> with a syntactic keyword <code>key</code>. + They use any Scheme objects as keywords. +- +-</p><pre>(define rest-list '(a 10 cc 30 40 b 20)) ++</p> ++<pre> ++(define rest-list '(a 10 cc 30 40 b 20)) + (alet ((key rest-list (a 1) (b 2) ((c 'cc) 3) . d)) (list a b c d)) + => (10 2 30 (40 b 20)) + +@@ -318,7 +342,8 @@ integrated into the <code>alet</code> and <code>alet*</code> with a + into the <code>alet</code> and <code>alet*</code> with a + syntactic keyword <code>rec</code>.</p> + +-<pre>(alet* ((a 1) ++<pre> ++(alet* ((a 1) + (rec (a 2) (b 3) (b (lambda () c)) (c a)) + (d 50)) + (list a (b) c d)) +@@ -330,7 +355,8 @@ into the <code>alet</code> and <code>alet*</code> with a + and <code>values</code> to handle multiple values with a syntactic + keyword <code>values</code> like <a href="#SRFI71">SRFI 71</a>.</p> + +-<pre>(alet ((a b (mu 1 2)) ++<pre> ++(alet ((a b (mu 1 2)) + (values c d (values 3 4)) ;This is different from <a href="#SRFI71">SRFI 71</a>. + ((e f) (mu 5 6)) + ((values g h) (values 7 8)) +@@ -347,7 +373,8 @@ keyword <code>values</code> like <a href="#SRFI71">SRFI 71</a>.</p> + environment in <code>alet</code> and as an intervening internal + environment in <code>alet*</code>.</p> + +-<pre>(alet ((a 1) ++<pre> ++(alet ((a 1) + (() (define a 10) (define b 100)) + (b a)) + (list a b)) +@@ -362,9 +389,10 @@ keyword <code>values</code> like <a href="#SRFI71">SRFI 71</a>.</p> + </li> + </ol> + +-<h1>Specification</h1> ++<h2>Specification</h2> + +-<pre>(mu <expr> ...) => (lambda (f) (f <expr> ...)) ++<pre> ++(mu <expr> ...) => (lambda (f) (f <expr> ...)) + (nu <expr> ... <exprn>) => (lambda (f) (apply f <expr> ... <exprn>)) + </pre> + +@@ -381,7 +409,8 @@ argument procedure of <code>mu</code> is called with the <expr>s, + and that of <code>nu</code> is applied to APPLY procedure with the + <expr>s.</p> + +-<pre>(alet (<binding spec> ...) body ...) ++<pre> ++(alet (<binding spec> ...) body ...) + (alet* (<binding spec> ...) body ...) + </pre> + +@@ -406,17 +435,20 @@ and that of <code>nu</code> is applied to APPLY procedure with the + <li><pre>(<binding spec1> <binding spec2> ... . <var>)</pre></li> + <li><pre>(() . <var>)</pre></li> + <li><pre>(and (<var1> <expr1> [<test1>]) (<var2> <expr2> [<test2>]) ...)</pre></li> +-<li><pre>(opt <rest list> ++<li><pre> ++(opt <rest list> + (<var1> <default1> [<test1> [<true substitute1> [<false substitute1>]]]) + ... + (<varn> <defaultn> [<testn> [<true substituten> [<false substituten>]]]) + . [<rest var>])</pre></li> +-<li><pre>(cat <rest list> ++<li><pre> ++(cat <rest list> + (<var1> <default1> [<test1> [<true substitute1> [<false substitute1>]]]) + ... + (<varn> <defaultn> [<testn> [<true substituten> [<false substituten>]]]) + . [<rest var>])</pre></li> +-<li><pre>(key <rest list> ++<li><pre> ++(key <rest list> + (<var spec1> <default1> [<test1> [<true substitute1> [<false substitute1>]]]) + ... + (<var specn> <defaultn> [<testn> [<true substituten> [<false substituten>]]]) +@@ -527,7 +559,8 @@ instead of signaling an error. If it returns a true value and there is a + substitute>. + </li> + +-<li><pre>(cat <rest list> ++<li><pre> ++(cat <rest list> + (<var1> <default1> [<test1> [<true substitute1> [<false substitute1>]]]) + ... + (<varn> <defaultn> [<testn> [<true substituten> [<false substituten>]]]) +@@ -549,7 +582,8 @@ and <test> returns a true value, <var> is finally bound to + the result of evaluating <true substitute>. + </li> + +-<li><pre>(key <rest list> ++<li><pre> ++(key <rest list> + (<var spec1> <default1> [<test1> [<true substitute1> [<false substitute1>]]]) + ... + (<var specn> <defaultn> [<testn> [<true substituten> [<false substituten>]]]) +@@ -642,7 +676,8 @@ This works as an intervening external environment in + </li> + </ol> + +-<pre>(alet name (<binding spec> ...) body ...) ++<pre> ++(alet name (<binding spec> ...) body ...) + (alet* name (<binding spec> ...) body ...) + </pre> + +@@ -651,9 +686,10 @@ These are the same as the named-<code>let</code> (R5RS, 4.2.4) except + binding specification. These allow all sorts of bindings in <binding + spec>.</p> + +-<h1>Examples</h1> ++<h2>Examples</h2> + +-<pre>(alet ((a (begin (display "1st") 1)) ++<pre> ++(alet ((a (begin (display "1st") 1)) + ((b c) 2 (begin (display "2nd") 3)) + (() (define m #f) (define n (list 8))) + ((d (begin (display "3rd") 4)) +@@ -749,14 +785,15 @@ spec>.</p> + "cdefghi" + </pre> + +-<h1>Implementation</h1> ++<h2>Implementation</h2> + + <p> + The following implementation is written in R5RS hygienic macros and + requires SRFI 23 (Error reporting mechanism). + </p> + +-<pre>;;; mu & nu ++<pre> ++;;; mu & nu + (define-syntax mu + (syntax-rules () + ((mu argument ...) +@@ -1888,7 +1925,7 @@ requires SRFI 23 (Error reporting mechanism). + (let ((e z)) bd ...)))) + </pre> + +-<h1>References</h1> ++<h2>References</h2> + + <ul> + <li><a name="R5RS">[R5RS]</a> Richard Kelsey, William Clinger, and Jonathan Rees: Revised(5) +@@ -1896,20 +1933,21 @@ requires SRFI 23 (Error reporting mechanism). + <a href="http://www.schemers.org/Documents/Standards/R5Rs/">Link</a></li> + <li><a name="SRFI2">[SRFI 2]</a> Oleg Kiselyov: <code>and-let*</code>: and <code>and</code> with local bindings, a guarded + <code>let*</code> special form. +- <a href="http://srfi.schemers.org/srfi-2/">Link</a></li> ++ <a href="srfi-2.html">Link</a></li> + <li><a name="SRFI11">[SRFI 11]</a> Lars T. Hansen: Syntax for receiving multiple values. +- <a href="http://srfi.schemers.org/srfi-11/">Link</a></li> ++ <a href="srfi-11.html">Link</a></li> + <li><a name="SRFI51">[SRFI 51]</a> Joo ChurlSoo: Handling rest list. +- <a href="http://srfi.schemers.org/srfi-51/">Link</a></li> ++ <a href="https://srfi.schemers.org/srfi-51/">Link</a></li> + <li><a name="SRFI71">[SRFI 71]</a> Sebastian Egner: Extended <code>let</code>-syntax for multiple values. +- <a href="http://srfi.schemers.org/srfi-71/">Link</a></li> ++ <a href="srfi-71.html">Link</a></li> + <li><a name="Scsh">[Scsh]</a> Olin Shivers, Brian Carlstrom, Martin Gasbichler, Mike Sperber +- <a href="http://www.scsh.net/">Link</a></li> ++ <a href="http://www.scsh.net">Link</a></li> + </ul> + +-<h1>Copyright</h1> +- ++<h2>Copyright</h2> ++<p> + Copyright (c) 2006 Joo ChurlSoo. ++</p> + <p> + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), +@@ -1917,10 +1955,12 @@ to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: +-</p><p> ++</p> ++<p> + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +-</p><p> ++</p> ++<p> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +@@ -1928,10 +1968,8 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +- +- </p><hr> ++</p> ++<hr /> + <address>Editor: <a href="mailto:srfi%20minus%20editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike + Sperber</a></address> +- +- + </body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html +index 73986bb..7920a28 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-87.html +@@ -1,44 +1,63 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +-<html><head><title>SRFI 87: => in case clauses</title></head><body> ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-87 ┃ ++┃ Commit: bc2424c1dc49a036f4d324b23720765c55d00c76 ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> ++ <title>SRFI 87: => in case clauses</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> + +-<h1>Title</h1> ++<body> + +-=> in case clauses ++<h1>SRFI 87: => in case clauses</h1> + +-<h1>Author</h1> ++<p>by Chongkai Zhu</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 87 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-87/srfi-87.html">https://srfi.schemers.org/srfi-87/srfi-87.html</a>.</p></blockquote></blockquote></blockquote> + +-Chongkai Zhu ++<h2>Status</h2> + +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each +-status that a SRFI can hold, see +-<a href="http://srfi.schemers.org/srfi-process.html">here</a>. +-To provide input on this SRFI, please <code> +-<a href="mailto:srfi-87@srfi.schemers.org">mailto:srfi-87@srfi.schemers.org</a></code>. +-See <a href="http://srfi.schemers.org/srfi-list-subscribe.html">instructions +-here</a> to subscribe to the list. You can access the discussion via +-<a href="http://srfi.schemers.org/srfi-87/mail-archive/maillist.html">the +-archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-87/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-<p> +-</p><ul> +- <li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-87/srfi-87.html?rev=1.1">2006/04/10</a></li> +- <li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-87/srfi-87.html?rev=1.2">2006/05/08</a></li> +- <li>Draft: 2006/04/10 - 2006/06/08</li> +- <li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-87/srfi-87.html?rev=1.3">2006/10/18</a></li> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+87+at+srfi+dotschemers+dot+org">srfi-87@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-87">archive</a>.</p> ++<ul> ++ <li>Received: <a href="https://srfi.schemers.org/srfi-87/srfi-87-1.1.html">2006-04-10</a></li> ++ <li>Revised: <a href="https://srfi.schemers.org/srfi-87/srfi-87-1.2.html">2006-05-08</a></li> ++ <li>Draft: 2006-04-10--2006-06-08</li> ++ <li>Final: <a href="https://srfi.schemers.org/srfi-87/srfi-87-1.3.html">2006-10-18</a></li> + </ul> + +-<h1>Abstract</h1>This SRFI proposes an extension to the <code>case</code> syntax ++<h2>Abstract</h2> ++<p> ++This SRFI proposes an extension to the <code>case</code> syntax + to allow the <code>=></code> clauses as in <code>cond</code>. +-<h1>Rationale</h1><code>case</code> is introduced as a syntax sugar based on ++</p> ++ ++<h2>Rationale</h2> ++<p> ++<code>case</code> is introduced as a syntax sugar based on + <code>cond</code>, which helps to save a explicit calling to <code>let</code>. + But without the <code>=></code> clause, if the <code>result </code>expression + needs the value of <code>key</code>, the <code>let </code>can't be saved. For an + easy example, suppose we want the following: ++</p> + <blockquote><pre>(case (get-symbol) + ((true) #t) + ((false) #f) +@@ -49,14 +68,15 @@ write:</p> + (cond ((eq? key 'true) #t) + ((eq? key 'false) #f) + (else key)))</pre></blockquote> +-<h1>Specification</h1> ++ ++<h2>Specification</h2> + <p>(Based on R5RS section 4.2.1 Conditionals)</p> + <dl> +- <dt><u>library syntax:</u> <b><a name="case">case</a></b> <i><key> <clause1> +- <clause2> ...</i> ++ <dt id="case"><u>library syntax:</u> <b>case</b> <i><key> <clause1> ++ <clause2> ...</i> + </dt><dd><em>Syntax:</em> <Key> may be any expression. Each <clause> + should have the form <pre><tt>((<datum1> ...) <expression1> <expression2> ...),</tt></pre> +- <p>where each <datum> is an external representation of some object. All ++ </dd></dl><p>where each <datum> is an external representation of some object. All + the <datum>s must be distinct. The last <clause> may be an "else + clause," which has the form </p><pre><tt>(else <expression1> <expression2> ...).</tt></pre> + <p><font color="#ff0000">Alternatively, a <clause> may be of the form +@@ -66,7 +86,7 @@ write:</p> + <p><em>Semantics:</em> A <samp>`case'</samp> expression is evaluated as + follows. <Key> is evaluated and its result is compared against each + <datum>. If the result of evaluating <key> is equivalent (in the +- sense of <samp>`eqv?'</samp>; see section see section <a href="http://www.swiss.ai.mit.edu/%7Ejaffer/r5rs_8.html#SEC49">6.1 Equivalence ++ sense of <samp>`eqv?'</samp>; see section see section <a href="http://www.swiss.ai.mit.edu/~jaffer/r5rs_8.html#SEC49">6.1 Equivalence + predicates</a>) to a <datum>, then the expressions in the corresponding + <clause> are evaluated from left to right and the result(s) of the last + expression in the <clause> is(are) returned as the result(s) of the +@@ -79,13 +99,14 @@ write:</p> + <expression> is evaluated. Its value must be a procedure that accepts + one argument; this procedure is then called on the value of <Key> and + the value(s) returned by this procedure is(are) returned by the +- <samp>`case'</samp> expression. </font></p></dd></dl> ++ <samp>`case'</samp> expression. </font></p> + <p>(Based on R5RS section 3.5 Proper tail recursion)</p> +-<dd>If a <tt>cond</tt> <font color="#ff0000">or <tt>case</tt></font> expression is in a tail context, and has a clause of the ++<p>If a <tt>cond</tt> <font color="#FF0000">or <tt>case</tt></font> expression is in a tail context, and has a clause of the + form <tt>(<expression<sub>1</sub>> => <expression<sub>2</sub>>)</tt> then the + (implied) call to the procedure that results from the evaluation of <expression<sub>2</sub>> +-is in a tail context. <expression<sub>2</sub>> itself is not in a tail context.</dd> +-<h1>Implementation</h1> ++is in a tail context. <expression<sub>2</sub>> itself is not in a tail context.</p> ++ ++<h2>Implementation</h2> + <blockquote><pre><code>(define-syntax case + (syntax-rules (else =>) + ((case (key ...) +@@ -118,24 +139,31 @@ is in a tail context. <expression<sub>2</sub>> itself is not in a tail con + (if (memv key '(atoms ...)) + (begin result1 result2 ...) + (case key clause clauses ...)))))</code></pre></blockquote> +-<h1>Copyright</h1>Copyright (C) 2006 Chongkai Zhu. All Rights Reserved. ++<h2>Copyright</h2> ++<p> ++Copyright (C) 2006 Chongkai Zhu. All Rights Reserved. ++</p> + <p>Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: +-</p><p>The above copyright notice and this permission notice shall be included in ++</p> ++<p> ++The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +-</p><p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++</p> ++<p> ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-</p><hr> ++</p> ++<hr /> + +-<address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike ++<address>Editor: <a href="mailto:srfi-editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike + Sperber</a></address><!-- Created: Tue Sep 29 19:20:08 EDT 1998 --><!-- hhmts start -->Last +-modified: Mon Apr 10 21:20:25 CEST 2006 <!-- hhmts end --> +-</body></html> ++modified: Mon Apr 10 21:20:25 CEST 2006 <!-- hhmts end --></body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html +index 0bf112a..4a64ddb 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-9.html +@@ -1,63 +1,90 @@ +-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"> +-<html> ++<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 3.2//EN" "http://www.w3.org/TR/HTML32.dtd"> ++<html lang="en"> + <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-9 ┃ ++┃ Commit: b627ef77ea0565a20656b95ed147ee5b746c825f ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 9: Defining Record Types</title> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> + </head> + + <body> + +-<H1>Title</H1> ++<h1>SRFI 9: Defining Record Types</h1> + +-SRFI 9: Defining Record Types ++<p>by Richard Kelsey</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 9 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-9/srfi-9.html">https://srfi.schemers.org/srfi-9/srfi-9.html</a>.</p></blockquote></blockquote></blockquote> + +-<H1>Author</H1> ++<h2>Status</h2> + +-Richard Kelsey +- +-<H1>Status</H1> +- +-This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see <A HREF="http://srfi.schemers.org/srfi-process.html">here</A>. +-You can access the discussion via <A HREF="http://srfi.schemers.org/srfi-9/mail-archive/maillist.html">the archive of the mailing list</A>. +-<P><UL> +-<LI>Received: 1999/07/01 +-<LI>Revised: 1999/08/25 +-<LI>Draft: 1999/07/07-1999/09/06 +-<LI>Final: 1999/09/09 +-</UL> +- +-<H1>Abstract</H1> ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+9+at+srfi+dotschemers+dot+org">srfi-9@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-9">archive</a>.</p> ++<ul> ++ <li>Received: 1999-07-01</li> ++ <li>Revised: 1999-08-25</li> ++ <li>Draft: 1999-07-07--1999-09-06</li> ++ <li>Final: 1999-09-09</li> ++</ul> + ++<h2>Abstract</h2> ++<p> + This SRFI describes syntax for creating new data types, called record types. + A predicate, constructor, and field accessors and modifiers are defined for + each record type. Each new record type is distinct from all existing types, + including other record types and Scheme's predefined types. ++</p> + +-<H1>Rationale</H1> +- ++<h2>Rationale</h2> ++<p> + Many Scheme implementations provide means for creating new types, + usually called either records or structures. + The <code>DEFINE-RECORD-TYPE</code> syntax described here is a slight +- simplification of one written for Scheme 48 by Jonathan Rees. ++ simplification of one written for Scheme 48 by Jonathan Rees. + Unlike many record-defining macros or special forms, it + does not create any new identifiers. + Instead, the names of the + record type, predicate, constructor, and so on are all listed explicitly + in the source. + This has the following advantages: +-<UL> +-<LI> It can be defined using a simple <code>SYNTAX-RULES</code> macro ++</p> ++<ul> ++ <li> ++ It can be defined using a simple <code>SYNTAX-RULES</code> macro + in Scheme implementations that provide a procedural interface + for creating record types. +-<LI> It does not restrict users to a particular naming convention. +-<LI> Tools like <code>grep</code> and GNU Emacs's tag facility will see the ++ </li> ++ <li> ++ It does not restrict users to a particular naming convention. ++ </li> ++ <li> ++ Tools like <code>grep</code> and GNU Emacs's tag facility will see the + defining occurrence of each identifier. +-</UL> +- +-<H1>Specification</H1> ++ </li> ++</ul> + ++<h2 id="define-record-type">Specification</h2> ++<p> + The syntax of a record-type definition is: +-<a name="define-record-type"></a> +-<PRE> ++</p> ++<pre> + <command or definition> + -> <record type definition> ; addition to 8.1.6 in R5RS + +@@ -72,70 +99,80 @@ The syntax of a record-type definition is: + + <field tag> -> <identifier> + <... name> -> <identifier> +-</PRE> +- ++</pre> ++<p> + <code>DEFINE-RECORD-TYPE</code> is generative: + each use creates a new record type that is distinct from all existing types, + including other record types and Scheme's predefined types. +- ++</p> ++<p> + Record-type definitions may only occur at top-level (there are two + possible semantics for `internal' record-type definitions, generative + and nongenerative, and no consensus as to which is better). +- +-<P> ++</p> ++<p> + An instance of <code>DEFINE-RECORD-TYPE</code> is equivalent to the following + definitions: +-<UL> +-<LI> <code><type name></code> is bound to a representation of the record ++</p> ++<ul> ++ <li> ++ <code><type name></code> is bound to a representation of the record + type itself. Operations on record types, such as defining print + methods, reflection, etc. are left to other SRFIs. +- +-<LI> <code><constructor name></code> is bound to a procedure that takes ++ </li> ++ <li> ++ <code><constructor name></code> is bound to a procedure that takes + as many arguments as there are <code><field tag></code>s in the + <code>(<constructor name> ...)</code> + subform and returns a new <code><type name></code> record. + Fields whose tags are listed with <code><constructor name></code> + have the corresponding argument as their + initial value. The initial values of all other fields are unspecified. +- +-<LI> <code><predicate name></code> is a predicate that returns #T when ++ </li> ++ <li> ++ <code><predicate name></code> is a predicate that returns #T when + given a value returned by <code><constructor name></code> and #F + for everything else. +- +-<LI> Each <code><accessor name></code> is a procedure that takes a record ++ </li> ++ <li> ++ Each <code><accessor name></code> is a procedure that takes a record + of type <code><type name></code> and returns the current value of the + corresponding field. + It is an error to pass an accessor a value which is not a record of + the appropriate type. +- +-<LI> Each <code><modifier name></code> is a procedure that takes a record ++ </li> ++ <li> ++ Each <code><modifier name></code> is a procedure that takes a record + of type <code><type name></code> and a value which becomes the new + value of the corresponding field; an unspecified value is returned. + It is an error to pass a modifier a first + argument which is not a record of the appropriate type. +-</UL> ++ </li> ++</ul> + +-<P> ++<p> + Records are disjoint from the types listed in Section 4.2 of R5RS. +- +-<P> ++</p> ++<p> + <code>Set!</code>ing the value of any of these identifiers has no + effect on the behavior of any of their original values. +- +-<P> ++</p> ++<p> + The following +-<PRE> ++</p> ++<pre> + (define-record-type :pare + (kons x y) + pare? + (x kar set-kar!) + (y kdr)) +-</PRE> ++</pre> ++<p> + defines <code>KONS</code> to be a constructor, <code>KAR</code> and + <code>KDR</code> to be accessors, <code>SET-KAR!</code> to be a modifier, + and <code>PARE?</code> to be a predicate for <code>:PARE</code>s. +- +-<PRE> ++</p> ++<pre> + (pare? (kons 1 2)) --> #t + (pare? (cons 1 2)) --> #f + (kar (kons 1 2)) --> 1 +@@ -143,27 +180,33 @@ and <code>PARE?</code> to be a predicate for <code>:PARE</code>s. + (let ((k (kons 1 2))) + (set-kar! k 3) + (kar k)) --> 3 +-</PRE> +- +-<H1>Implementation</H1> ++</pre> + ++<h2>Implementation</h2> ++<p> + This code is divided into three layers. In top-down order these are: +-<OL> +-<LI> Syntax definitions for <code>DEFINE-RECORD-TYPE</code> and an auxiliary +- macro. +-<LI> An implementation of record types with a procedural interface. ++</p> ++<ol> ++ <li> ++Syntax definitions for <code>DEFINE-RECORD-TYPE</code> and an auxillary macro. ++ </li> ++ <li> ++An implementation of record types with a procedural interface. + Some Scheme implementations already have something close to this. +-<LI> Vector-like records implemented in R5RS. This redefines some standard ++ </li> ++ <li> ++Vector-like records implemented in R5RS. This redefines some standard + Scheme procedures and therefor must be loaded before any other code, including + part 2 above. Note that these procedures can be used to break the + record-type abstraction (for example, <code>RECORD-SET!</code> can be used + to modify the type of a record). Access to these procedures should be + restricted. +-</OL> ++ </li> ++</ol> + +-<H2>Syntax definitions</H2> ++<h3>Syntax definitions</h3> + +-<PRE> ++<pre> + ; Definition of DEFINE-RECORD-TYPE + + (define-syntax define-record-type +@@ -193,23 +236,23 @@ restricted. + (begin + (define accessor (record-accessor type 'field-tag)) + (define modifier (record-modifier type 'field-tag)))))) +-</PRE> ++</pre> + +-<H2>Record types</H2> ++<h3>Record types</h3> + +-<PRE> ++<pre> + ; We define the following procedures: + ; +-; (make-record-type <type-name <field-names>) -> <record-type> +-; (record-constructor <record-type<field-names>) -> <constructor> +-; (record-predicate <record-type>) -> <predicate> +-; (record-accessor <record-type <field-name>) -> <accessor> +-; (record-modifier <record-type <field-name>) -> <modifier> ++; (make-record-type <type-name <field-names>) -> <record-type> ++; (record-constructor <record-type<field-names>) -> <constructor> ++; (record-predicate <record-type>) -> <predicate> ++; (record-accessor <record-type <field-name>) -> <accessor> ++; (record-modifier <record-type <field-name>) -> <modifier> + ; where +-; (<constructor> <initial-value> ...) -> <record> +-; (<predicate> <value>) -> <boolean> +-; (<accessor> <record>) -> <value> +-; (<modifier> <record> <value>) -> <unspecific> ++; (<constructor> <initial-value> ...) -> <record> ++; (<predicate> <value>) -> <boolean> ++; (<accessor> <record>) -> <value> ++; (<modifier> <record> <value>) -> <unspecific> + + ; Record types are implemented using vector-like records. The first + ; slot of each record contains the record's type, which is itself a +@@ -308,19 +351,19 @@ restricted. + type)) + (record-set! thing index value) + (error "modifier applied to bad value" type tag thing))))) +-</PRE> ++</pre> + +-<H2>Records</H2> ++<h3>Records</h3> + +-<PRE> ++<pre> + ; This implements a record abstraction that is identical to vectors, + ; except that they are not vectors (VECTOR? returns false when given a + ; record and RECORD? returns false when given a vector). The following + ; procedures are provided: +-; (record? <value>) -> <boolean> +-; (make-record <size>) -> <record> +-; (record-ref <record> <index>) -> <value> +-; (record-set! <record> <index> <value>) -> <unspecific> ++; (record? <value>) -> <boolean> ++; (make-record <size>) -> <record> ++; (record-ref <record> <index>) -> <value> ++; (record-set! <record> <index> <value>) -> <unspecific> + ; + ; These can implemented in R5RS Scheme as vectors with a distinguishing + ; value at index zero, providing VECTOR? is redefined to be a procedure +@@ -366,9 +409,9 @@ restricted. + + (define (record-set! record index value) + (vector-set! record (+ index 1) value)) +-</PRE> ++</pre> + +-<H1>Copyright</H1> ++<h2>Copyright</h2> + + <p>Copyright (C) Richard Kelsey (1999). All Rights Reserved. </p> + +@@ -395,9 +438,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> + +-<hr> ++<hr /> + +- <address>Editor: <a href="mailto:srfi-editors@srfi.schemers.org">Mike Sperber</a></address> ++ <address>Editor: <a href="mailto:srfi-editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + + </body> + </html> +diff --git a/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html b/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html +index 8ff8dfb..f5edd0e 100644 +--- a/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html ++++ b/srfi-doc/srfi/scribblings/srfi-std/srfi-98.html +@@ -1,57 +1,63 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +-<html><head> +-<meta http-equiv="content-type" content="text/html; charset=UTF-8"><!-- DO NOT EDIT THIS FILE--> +-<!-- Edit the .tex version instead--> +- +- ++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8" /> ++<!-- ++┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ++┃ This file was automatically transformed for Racket. ┃ ++┃ ┃ ++┃ Source: https://github.com/scheme-requests-for-implementation/srfi-98 ┃ ++┃ Commit: 39560302c1019b4eae386b510bb513e481ac09fd ┃ ++┃ ┃ ++┃ Please DO NOT edit this file by hand. ┃ ++┃ Whenever possible, contribute changes upstream. ┃ ++┃ For Racket-specific changes, edit the transformation script: ┃ ++┃ ┃ ++┃ "srfi-sync.rkt" in https://github.com/racket/srfi ┃ ++┃ ┃ ++┃ and regenerate all of these files. ┃ ++┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ++--> + <title>SRFI 98: An interface to access environment variables.</title> +- </head><body> +- +-<h1>Title</h1> +- +-An interface to access environment variables. +- +-<h1>Author</h1> +- +-Taro Minowa(Higepon) +- +-<h1>Status</h1> +- +-This SRFI is currently in ``final'' status. To see an explanation of +-each status that a SRFI can hold, see <a href="http://srfi.schemers.org/srfi-process.html">here</a>. +- +-To provide input on this SRFI, please send email to +-<a href="mailto:srfi%20minus%2098%20at%20srfi%20dot%20schemers%20dot%20org"> +-<code><srfi minus 98 at srfi dot schemers dot org></code></a>. See +-<a href="http://srfi.schemers.org/srfi-list-subscribe.html">instructions here</a> to subscribe to +-the list. You can access the discusssion via +-<a href="http://srfi.schemers.org/srfi-98/mail-archive/maillist.html">the archive of the mailing list</a>. +-You can access +-post-finalization messages via +-<a href="http://srfi.schemers.org/srfi-98/post-mail-archive/maillist.html"> +-the archive of the mailing list</a>. +-<p></p><ul> +- +-<li>Received: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.2">2008/07/06</a></li> +-<li>Draft: 2008/07/06 - 2008/09/06</li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.3">2008/07/18</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.4">2008/07/18</a></li> +-<li>Revised: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.5">2008/08/14</a></li> +-<li>Final: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.7">2008/09/19</a></li> +-<li>R6RS library name: <a href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-98/srfi-98.html?rev=1.8">2009/02/16</a></li> ++ <meta content="width=device-width, initial-scale=1" name="viewport" /> ++ <link rel="stylesheet" type="text/css" href="racket-srfi.css" /> ++ <script type="text/javascript" src="../../doc-site.js"></script> ++ </head> ++ ++ <body> ++ ++<h1>SRFI 98: An interface to access environment variables.</h1> ++ ++<p>by Taro Minowa (Higepon)</p> ++<blockquote class="refpara racket-srfi-note"><blockquote class="refcolumn"><blockquote class="refcontent"><p>This copy of the SRFI 98 specification document ++is distributed as part of the Racket package ++<a href="../index.html"><span class="stt">srfi-doc</span></a>.</p><p>The canonical source of this document is ++<a href="https://srfi.schemers.org/srfi-98/srfi-98.html">https://srfi.schemers.org/srfi-98/srfi-98.html</a>.</p></blockquote></blockquote></blockquote> ++ ++<h2>Status</h2> ++ ++<p>This SRFI is currently in <em>final</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+98+at+srfi+dotschemers+dot+org">srfi-98@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-98">archive</a>.</p> ++<ul> ++<li>Received: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.2.html">2008-07-06</a></li> ++<li>Draft: 2008-07-06--2008-09-06</li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.3.html">2008-07-18</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.4.html">2008-07-18</a></li> ++<li>Revised: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.5.html">2008-08-14</a></li> ++<li>Final: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.7.html">2008-09-19</a></li> ++<li>R6RS library name: <a href="https://srfi.schemers.org/srfi-98/srfi-98-1.8.html">2009-02-16</a></li> + </ul> + +-<h1>Abstract</h1> ++<h2>Abstract</h2> + This SRFI specifies the procedure get-environment-variable, which gets + the value of the specified environment variable, and the procedure + get-environment-variables, which gets an association list of all + environment variables. + +-<h1>Rationale</h1> ++<h2>Rationale</h2> + <p>Most operating systems provide a mechanism for passing auxiliary + parameters implicitly to child processes. Usually, this mechanism is + called "the environment", and is conceptually a map from string names +-to string values. The string names are called environment ++to string values. The string names are called enviornment + variables.</p> + + <p>Some applications rely on environment variables to modify their +@@ -60,9 +66,8 @@ protocols rely on environment variables as a form of interprocess + communication. For example, most implementations of the common + gateway interface (CGI) use environment variables to pass + Meta-Variables from the server to the script <a href="#0.1_cgi">[1]</a>. +-Environment variables are also required +-by <a href="http://srfi.schemers.org/srfi-96/srfi-96.html" title="SRFI +-96: SLIB Prerequisites">SRFI 96: SLIB Prerequisites</a>. ++Environment variables are also required by ++<a href="https://srfi.schemers.org/srfi-96/srfi-96.html" title="SRFI 96: SLIB Prerequisites">SRFI 96: SLIB Prerequisites</a>. + Providing a means to access environment variables is therefore + indispensable for writing practical programs in Scheme. + </p> +@@ -83,10 +88,10 @@ Meta-Variables "QUERY_STRING", "CONTENT_LENGTH" and + </pre> + + <p><a name="0.1_cgi">[1]</a> The Common Gateway Interface (CGI) Version 1.1, RFC3875, <a href="http://www.ietf.org/rfc/rfc3875" target="_blank">http://www.ietf.org/rfc/rfc3875</a>.</p> +-<h1>Specification</h1> ++<h2>Specification</h2> + <pre>R6RS library name</pre> + The following two procedures belong to the R6RS library named (srfi :98 os-environment-variables). +-<pre>Function: <a name="get-environment-variable">get-environment-variable</a> name</pre>Returns the value of ++<pre id="get-environment-variable">Function: get-environment-variable name</pre>Returns the value of + the named environment variable as a string, or #f if the named + environment variable is not found. The name argument is expected to be + a string. +@@ -96,19 +101,21 @@ the environment variable. + If get-environment-variable can't decode the value, get-environment-variable may raise an exception. + <pre>(get-environment-variable "PATH") => "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" + </pre> +-<pre>Function: <a name="get-environment-variables">get-environment-variables</a></pre> ++<pre id="get-environment-variables">Function: get-environment-variables</pre> + Returns names and values of all the environment variables as an a-list. + The same decoding considerations as for get-environment-variable apply. + <pre>(get-environment-variables) => (("PATH" . "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin") ("USERNAME" . "taro")) + </pre> + +-<h1>Implementation</h1> +-<h2>Gauche</h2> +-<pre>(define get-environment-variable sys-getenv) ++<h2>Implementation</h2> ++<h3>Gauche</h3> ++<pre> ++(define get-environment-variable sys-getenv) + (define get-environment-variables sys-environ->alist) + </pre> +-<h2>Scheme48</h2> +-<pre>(define (get-environment-variable name) ++<h3>Scheme48</h3> ++<pre> ++(define (get-environment-variable name) + (cond + ((lookup-environment-variable name) => os-string->string) + (else #f))) +@@ -117,17 +124,19 @@ The same decoding considerations as for get-environment-variable apply. + (cons (os-string->string (car p)) (os-string->string (cdr p)))) + (environment-alist))) + </pre> +-<h2>scsh</h2> +-<pre>(define get-environment-variable getenv) ++<h3>scsh</h3> ++<pre> ++(define get-environment-variable getenv) + (define get-environment-variables env->alist) + </pre> + +-<h2>SCM</h2> +-<pre>(define get-environment-variable getenv) ++<h3>SCM</h3> ++<pre> ++(define get-environment-variable getenv) + (define get-environment-variables getenv) + </pre> + +-<h1>Issues</h1> ++<h2>Issues</h2> + <p>get-environment-variable is expected to return a "Scheme string". + Unfortunately, many current platforms, including POSIX-like ones, do + not require environment variables to be interpretable as sequences of +@@ -143,7 +152,7 @@ implementations, and captures the semantically desirable behavior in + the common case that the byte sequence is interpretable as a string.</p> + + <a name="0.1_appendix"></a> +-<h1>Appendix: Existing implementations</h1> ++<h2>Appendix: Existing implementations</h2> + <table border="1"> + <tbody><tr><th>Scheme implementation</th><th>get environment variable</th><th>get all the environment variables as an a-list</th></tr> + <tr><td>Bigloo</td><td>(getenv name) => (or string? false) name:string?</td><td> </td></tr> +@@ -161,10 +170,10 @@ the common case that the byte sequence is interpretable as a string.</p> + <tr><td>STklos</td><td>(getenv name) => (or string? false) name:string?</td><td>(getenv)</td></tr> + <tr><td>SCM</td><td>(getenv name) => (or string? false) name:string?</td><td>(getenv)</td></tr> + </tbody></table> +-<h1>Acknowledgements</h1> ++<h2>Acknowledgements</h2> + Thanks to Shiro Kawai, Alexey Radul, jmuk, Kokosabu, leque and all the members of the #Lisp_Scheme IRC channel on Freenode. +-<h1>Copyright</h1> +-Copyright (C) Taro Minowa(Higepon) (2008). All Rights Reserved. ++<h2>Copyright</h2> ++Copyright (C) Taro Minowa (Higepon) (2008). All Rights Reserved. + <p> + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the +@@ -185,7 +194,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + </p> +- <hr> ++ <hr /> + <address>Editor: <a href="mailto:srfi-editors%20at%20srfi%20dot%20schemers%20dot%20org">Mike Sperber</a></address> + <!-- Last modified: Sun Jan 28 14:21:14 MET 2007 --> + </body></html> +diff --git a/srfi-doc/srfi/scribblings/srfi.scrbl b/srfi-doc/srfi/scribblings/srfi.scrbl +index 4ab1397..3b1807d 100644 +--- a/srfi-doc/srfi/scribblings/srfi.scrbl ++++ b/srfi-doc/srfi/scribblings/srfi.scrbl +@@ -1,12 +1,23 @@ + #lang scribble/doc +-@(require srfi/scribblings/util ++@(require "util.rkt" + scribble/manual + scribble/eval + scriblib/render-cond + scribble/core + scribble/html-properties + (for-syntax scheme/base) +- (for-label scheme/base ++ (for-label (except-in scheme/base ++ make-date ;; but we DO want `date` ++ date? ++ date-second ++ date-minute ++ date-hour ++ date-day ++ date-month ++ date-year ++ date-week-day ++ date-year-day) ++ srfi/19 + racket/stream)) + + @; ---------------------------------------------------------------------- +@@ -27,7 +38,7 @@ which can be implemented as libraries. To import the bindings of SRFI + ] + + This document lists the SRFIs that are supported by Racket and +-provides a link to the original SRFI specification (which is also ++provides links to the original SRFI specifications (which are also + distributed as part of Racket's documentation). + + @table-of-contents[] +@@ -95,7 +106,7 @@ functions. + (concatenate #f "concatenate") + (concatenate! #f "concatenate!") + (reverse #f "reverse") +- (reverse! #f "srfi-1.html") ++ (reverse! #f "reverse!") + (append-reverse #f "append-reverse") + (append-reverse! #f "append-reverse!") + (zip #f "zip") +@@ -114,7 +125,7 @@ functions. + (unfold #f "unfold") + (unfold-right #f "unfold-right") + (map #f "map") +- (for-each #f "srfi-1.html") ++ (for-each #f "for-each") + (append-map #f "append-map") + (append-map! #f "append-map!") + (map! #f "map!") +@@ -153,7 +164,6 @@ functions. + (alist-copy #f "alist-copy") + (alist-delete #f "alist-delete") + (alist-delete! #f "alist-delete!") +- (lset #f "lset") + (lset= #f "lset=") + (lset-adjoin #f "lset-adjoin") + (lset-union #f "lset-union") +@@ -198,6 +208,11 @@ are also available from @racketmodname[scheme/foreign]. + + @; ---------------------------------------- + ++@; special case for historical license reasons ++@include-section["srfi-5-doc-free.scrbl"] ++ ++@; ---------------------------------------- ++ + @srfi[6]{Basic String Ports} + + @redirect[6 '( +@@ -430,7 +445,7 @@ are also available from @racketmodname[scheme/foreign]. + @srfi[17]{Generalized set!} + + @redirect[17 '( +- (set! #t "set!") ++ (set! #t "!set") + (getter-with-setter #f "getter-with-setter") + )] + +@@ -439,13 +454,13 @@ are also available from @racketmodname[scheme/foreign]. + @srfi[19]{Time Data Types and Procedures} + + @redirect[19 '( +- (time-duration #f "") ++ (time-duration #f "time-duration") + (time-monotonic #f "time-monotonic") + (time-process #f "time-process") + (time-tai #f "time-tai") + (time-thread #f "time-thread") + (time-utc #f "time-utc") +- (current-date #f "") ++ (current-date #f "current-date") + (current-julian-day #f "current-julian-day") + (current-modified-julian-day #f "current-modified-julian-day") + (current-time #f "current-time") +@@ -526,20 +541,31 @@ to the one provided by @racketmodname[racket/base] in most cases + (see @racket[date]). + + For backwards compatibility, when an invalid date field value is +-provided to the SRFI constructor, the constructor will produce a lax +-date structure. A lax date structure is @emph{not} compatible with +-functions from @racketmodname[racket/base] or ++provided to the SRFI constructor, the constructor will produce a ++@deftech{lax date structure}. A lax date structure is @emph{not} ++compatible with functions from @racketmodname[racket/base] or + @racketmodname[racket/date]. SRFI functions such as + @racket[string->date] may return a lax date structure depending on the + format string. ++The predicate @racket[lax-date?] recognizes lax dat structures. ++ ++As an extension, Racket's implementation of @racket[string->date] ++supports @litchar{~?} as a conversion specifier: ++it parses one- and two-digit years like @litchar{~y} ++and three- and four-digit years like @litchar{~Y}. + + @(define srfi-19-eval (make-base-eval)) + @(srfi-19-eval '(require srfi/19)) + ++@examples[#:eval srfi-19-eval ++ (string->date "4-1-99" "~d-~m-~?") ++ (string->date "4-1-1999" "~d-~m-~?") ++] ++ + @defproc[(lax-date? [v any/c]) boolean?]{ + +-Returns @racket[#t] if @racket[_v] is a lax date structure. Otherwise +-returns @racket[#f]. ++Returns @racket[#t] if @racket[_v] is a @tech{lax date structure}. ++Otherwise, returns @racket[#f]. + + @examples[#:eval srfi-19-eval + (lax-date? (make-date 0 19 10 10 14 "bogus" "bogus" 0)) +@@ -688,8 +714,8 @@ This SRFI's syntax is part of Racket's default reader and printer. + + @redirect[40 '( + (stream-cons #t "stream-cons") +- (stream? #f "stream?") +- (stream-null? #f "stream-null?") ++ (stream? #f "streamp") ++ (stream-null? #f "stream-nullp") + (stream-car #f "stream-car") + (stream-cdr #f "stream-cdr") + (stream-delay #t "stream-delay") +@@ -787,7 +813,7 @@ same as from @racketmodname[racket/stream]. + (:real-range #t ":real-range") + (:char-range #t ":char-range") + (:port #t ":port") +- (:dispatched #t "") ++ (:dispatched #t ":dispatched") + (:generator-proc #t ":generator-proc") + (:do #t ":do") + (:let #t ":let") +@@ -814,7 +840,7 @@ from @racketmodname[scheme/base] and @mz-if from + (vector-append #f "vector-append") + (vector-concatenate #f "vector-concatenate") + (vector? #f "vector-p") +- (vector-empty? #f "vector-empty?") ++ (vector-empty? #f "vector-empty-p") + (vector= #f "vector-eq") + (vector-ref #f "vector-ref") + (vector-length #f "vector-length") +@@ -837,10 +863,10 @@ from @racketmodname[scheme/base] and @mz-if from + (vector-reverse! #f "vector-reverse-bang") + (vector-copy! #f "vector-copy-bang") + (vector-reverse-copy! #f "vector-reverse-copy-bang") +- (vector->list #f "vector->list") +- (reverse-vector->list #f "reverse-vector->list") +- (list->vector #f "list->vector") +- (reverse-list->vector #f "reverse-list->vector") ++ (vector->list #f "vector-to-list") ++ (reverse-vector->list #f "reverse-vector-to-list") ++ (list->vector #f "list-to-vector") ++ (reverse-list->vector #f "reverse-list-to-vector") + )] + + @; ---------------------------------------- +diff --git a/srfi-doc/srfi/scribblings/util.rkt b/srfi-doc/srfi/scribblings/util.rkt +index d67c82a..786fea9 100644 +--- a/srfi-doc/srfi/scribblings/util.rkt ++++ b/srfi-doc/srfi/scribblings/util.rkt +@@ -59,3 +59,20 @@ + + @(define srfi-std (style #f (list (install-resource "srfi-std")))) + ++@(define srfi-license-history-url ++ ;; explains the "historical reasons" for the restrictive license on SRFI 5 ++ "https://srfi-email.schemers.org/srfi-announce/msg/2652023/") ++@(define srfi-5-std-taglet "srfi-5-std") ++@(define srfi-5-license-taglet "srfi-5-std-license") ++ ++@(define (racket-license-link . args) ++ ;; FIXME why does this not work? ++ #; ++ (apply seclink "License" #:doc '(lib "scribblings/main/license.scrbl") args) ++ (define (link base) ++ (apply hyperlink (string-append base "license/index.html") args)) ++ (cond-element ++ [(or latex text) ++ (link "https://docs.racket-lang.org/")] ++ [else ++ (link "../")])) +diff --git a/srfi-lib/info.rkt b/srfi-lib/info.rkt +index da0d08d..56d31b7 100644 +--- a/srfi-lib/info.rkt ++++ b/srfi-lib/info.rkt +@@ -2,6 +2,8 @@ + + (define collection 'multi) + ++(define version "1.1") ++ + (define deps '("scheme-lib" + "base" + "srfi-lite-lib" +diff --git a/srfi-lib/srfi/5/let.rkt b/srfi-lib/srfi/5/let.rkt +index a1a88fb..19be931 100644 +--- a/srfi-lib/srfi/5/let.rkt ++++ b/srfi-lib/srfi/5/let.rkt +@@ -7,51 +7,62 @@ + (define-syntax (s:let stx) + (define-syntax-class loopid + #:description "loop identifier" ++ #:opaque + (pattern :id)) + (define-syntax-class binding-pair + #:description "binding pair" + (pattern [name:id arg:expr])) +- (define-syntax-class rest-binding +- #:description "\"rest\" binding" +- (pattern [rest-name:id rest-arg:expr ...])) +- (define-splicing-syntax-class let-style-bindings +- #:description "let-style bindings" +- #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- ;; in let-style bindings, rest-binding only allowed w/ +- ;; at least one binding-pair +- (pattern (~seq (~optional loop*:loopid) +- (:binding-pair ...)) +- #:with (rest-arg ...) #'() +- #:attr rest-name #f) +- (pattern (~seq (~optional loop*:loopid) +- (:binding-pair ...+ . :rest-binding)))) +- (define-splicing-syntax-class define-style-bindings +- #:description "define-style bindings" +- #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- (pattern (~seq (loop*:loopid :binding-pair ...)) +- #:with (rest-arg ...) #'() +- #:attr rest-name #f) +- (pattern (~seq (loop*:loopid +- :binding-pair ... +- . :rest-binding)))) +- (define-splicing-syntax-class bindings ++ (define-splicing-syntax-class maybe-rest-binding + #:description #f ++ #:no-delimit-cut ++ (pattern (~describe "\"rest\" binding" ++ (~seq (~describe #:opaque "\"rest\" identifier" ++ rest-name:id) ++ ~! ++ (~describe #:opaque "\"rest\" init expression" ++ rest-arg:expr) ++ ...))) ++ (pattern (~seq) ++ #:attr rest-name #f ++ #:with (rest-arg ...) #'())) ++ (define-splicing-syntax-class bindings ++ #:description "bindings" + #:attributes (loop* [name 1] [arg 1] rest-name [rest-arg 1]) +- (pattern :let-style-bindings) +- (pattern :define-style-bindings)) ++ (pattern ++ (~describe ++ "\"named let\"-style bindings" ++ (~seq loop*:loopid ++ ~! ++ (~describe ++ "parenthesized sequence of binding pairs with optional \"rest\" binding" ++ (:binding-pair ... :maybe-rest-binding))))) ++ (pattern ++ (~describe ++ "\"define\"-style bindings" ++ (~seq (loop*:loopid ~! :binding-pair ... :maybe-rest-binding)))) ++ (pattern ++ (~describe ++ "\"let\"-style bindings with no loop identifier" ++ (~seq ++ (~or* (~describe #:opaque "empty sequence of binding pairs" ++ (~and () (:binding-pair ... :maybe-rest-binding))) ++ (~describe ++ "parenthesized sequence of one or more binding pairs with optional \"rest\" binding" ++ (:binding-pair ...+ :maybe-rest-binding))))) ++ #:attr loop* #f)) + (syntax-parse stx +- [(_ () body:expr ...+) +- #'(let () body ...)] + [(_ :bindings +- body:expr ...+) ++ (~describe "body forms" (~seq body:expr ...+))) ++ ;; it is NOT an error for loop* to be shaddowed: ++ ;; see https://srfi-email.schemers.org/srfi-5/msg/18712014/ + #:fail-when (check-duplicate-identifier + (syntax->list #'(name ... (~? rest-name)))) + "duplicate variable name" +- #:with loop (or (attribute loop*) #'tmp-loop) +- #'(letrec ([loop (λ (~? (name ... . rest-name) +- (name ...)) +- body ...)]) ++ #:with loop (or (attribute loop*) #'anonymous-srfi-5-let) ++ #`(letrec ([loop #,(syntax-property ++ (syntax/loc stx ++ (λ (~? (name ... . rest-name) ++ (name ...)) ++ body ...)) ++ 'inferred-name (or (attribute loop*) (void)))]) + (loop arg ... rest-arg ...))])) +- +- +- +diff --git a/srfi-test/tests/srfi/5/srfi-5-test.rkt b/srfi-test/tests/srfi/5/srfi-5-test.rkt +index 47bb660..9b3ab73 100644 +--- a/srfi-test/tests/srfi/5/srfi-5-test.rkt ++++ b/srfi-test/tests/srfi/5/srfi-5-test.rkt +@@ -27,16 +27,24 @@ + (cons x y)) + '(1 2) + "rest binding w/ 1 value") ++ (check-equal? (s:let ([x 1] y 2) ++ (cons x y)) ++ '(1 2) ++ "rest binding w/ 1 value (no dot)") + (check-equal? (s:let ([x 1] . [y 2 3]) + (cons x y)) + '(1 2 3) + "rest binding w/ multiple values") ++ (check-equal? (s:let ([x 1] y 2 3) ++ (cons x y)) ++ '(1 2 3) ++ "rest binding w/ multiple values (no dot)") + (check-exn exn:fail:syntax? + (λ () (convert-syntax-error (s:let ([x 1 2]) x))) +- "rest binding alone is an error")) ++ "malformed binding pair is an error")) + + (test-case +- "let-style loop" ++ "\"named let\"-style loop" + (check-equal? (s:let loop () 1) + 1 + "loop w/ no bindings is ok") +@@ -61,6 +69,13 @@ + [else (list args)])) + '((a) (b) (c d)) + "rest binding w/ 1 initial value") ++ (check-equal? (s:let loop ([continue? 0] args 'a) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding w/ 1 initial value (no dot)") + (check-equal? (s:let loop ([continue? 0] + . [args 'a 'a1 'a2]) + (case continue? +@@ -69,12 +84,48 @@ + [else (list args)])) + '((a a1 a2) (b) (c d)) + "rest binding w/ multiple initial values") ++ (check-equal? (s:let loop ([continue? 0] args 'a 'a1 'a2) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a a1 a2) (b) (c d)) ++ "rest binding w/ multiple initial values (no dot)") ++ (check-equal? (s:let loop (x) ++ x) ++ '() ++ "rest binding alone w/ 0 initial values") ++ (check-equal? (s:let loop (x 1) ++ x) ++ '(1) ++ "rest binding alone w/ 1 initial value") ++ (check-equal? (s:let loop (x 1 2) ++ x) ++ '(1 2) ++ "rest binding alone w/ multiple initial values") ++ (check-equal? (s:let a (b (+ 1)) ++ b) ++ '(1) ++ ;; "confusable" here means that the expression (+ 1) ++ ;; could be confused for a binding pair ++ "rest binding alone w/ confusable initial value") ++ (check-exn (λ (e) ++ (and (exn:fail:syntax? e) ++ (regexp-match? #rx"^x: unbound" (exn-message e)))) ++ (λ () ++ (convert-syntax-error ++ (s:let a (b [x 1]) 2))) ++ "rest binding alone: correct error when confused w/ define") ++ (check-pred procedure? ++ (s:let loop (args 1 2 3) ++ loop) ++ "rest binding alone: does bind procedure") + (check-exn exn:fail:syntax? + (λ () (convert-syntax-error (s:let loop ([x 1 2]) x))) +- "rest binding alone is an error")) ++ "malformed binding pair is an error")) + + (test-case +- "define-style loop" ++ "\"define\"-style loop" + (check-equal? (s:let (loop) 1) + 1 + "loop w/ no bindings is ok") +@@ -91,6 +142,20 @@ + (list x))) + '(1 2) + "loop w/ 2 normal args") ++ (check-equal? (s:let (loop [continue? 0] . [args]) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding w/ 0 initial values") ++ (check-equal? (s:let (loop [continue? 0] args) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding w/ 0 initial values (no dot)") + (check-equal? (s:let (loop [continue? 0] + . [args 'a]) + (case continue? +@@ -99,24 +164,94 @@ + [else (list args)])) + '((a) (b) (c d)) + "rest binding w/ 1 initial value") +- (check-equal? (s:let (loop [continue? 0] +- . [args 'a 'a1 'a2]) ++ (check-equal? (s:let (loop [continue? 0] args 'a) ++ (case continue? ++ [(0) (cons args (loop 1 'b))] ++ [(1) (cons args (loop 2 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding w/ 1 initial value (no dot)") ++ (check-equal? (s:let (loop [continue? 0] args 'a 'a1 'a2) + (case continue? + [(0) (cons args (loop 1 'b))] + [(1) (cons args (loop 2 'c 'd))] + [else (list args)])) + '((a a1 a2) (b) (c d)) +- "rest binding w/ multiple initial values") ++ "rest binding w/ multiple initial values (no dot)") ++ (check-equal? (s:let (loop . [args]) ++ (case args ++ [(()) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding alone w/ 0 initial values") ++ (check-equal? (s:let (loop args) ++ (case args ++ [(()) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '(() (b) (c d)) ++ "rest binding alone w/ 0 initial values (no dot)") + (check-equal? (s:let (loop . [args 'a]) + (case args + [((a)) (cons args (loop 'b))] + [((b)) (cons args (loop 'c 'd))] + [else (list args)])) + '((a) (b) (c d)) +- "define-style loop can have only rest arg")) +- +- (check-exn exn:fail:syntax? +- (λ () +- (convert-syntax-error +- (s:let a (b [x 1]) x))) +- "combining let- and define- style loop names is an error"))) ++ "rest binding alone w/ 1 initial value") ++ (check-equal? (s:let (loop args 'a) ++ (case args ++ [((a)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a) (b) (c d)) ++ "rest binding alone w/ 1 initial value (no dot)") ++ (check-equal? (s:let (loop . [args 'a1 'a2 'a3]) ++ (case args ++ [((a1 a2 a3)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a1 a2 a3) (b) (c d)) ++ "rest binding alone w/ multiple initial values") ++ (check-equal? (s:let (loop args 'a1 'a2 'a3) ++ (case args ++ [((a1 a2 a3)) (cons args (loop 'b))] ++ [((b)) (cons args (loop 'c 'd))] ++ [else (list args)])) ++ '((a1 a2 a3) (b) (c d)) ++ "rest binding alone w/ multiple initial values (no dot)")) ++ (test-case ++ "shaddowing" ++ ;; See: https://srfi-email.schemers.org/srfi-5/msg/18712014/ ++ (check-equal? (s:let x ((x 1)) x) ++ 1 ++ "let-style: loop id can be shaddowed") ++ (check-equal? (s:let (x (x 1)) x) ++ 1 ++ "define-style: loop id can be shaddowed") ++ (check-eq? (object-name (s:let f () f)) ++ 'f ++ "let-style object name") ++ (check-eq? (object-name (s:let (g) g)) ++ 'g ++ "define-style object name") ++ (check-exn #rx"duplicate" ++ (λ () (convert-syntax-error (s:let loop ((x 1) x) #t))) ++ "let-style: check duplicate ids") ++ (check-exn #rx"duplicate" ++ (λ () (convert-syntax-error (s:let (loop (x 1) x) #t))) ++ "define-style: check duplicate ids") ++ (check-exn #rx"duplicate" ++ (λ () (convert-syntax-error (s:let ((x 1) (x 2)) #t))) ++ "non-loop: check duplicate ids")) ++ (test-case ++ "ambiguous \"define\"-style loop: preserve compatible behavior" ++ ;; See: https://srfi-email.schemers.org/srfi-5/msg/18709896/ ++ (check-pred procedure? ++ (s:let (ambiguous (+ 1) (- 2) (list 5)) ++ ambiguous) ++ "ambiguous is not a rest binding") ++ (check-equal? (s:let (ambiguous (+ 1) (- 2) (abs -7)) ++ (list + - abs)) ++ '(1 2 -7) ++ "binds identifiers")))) +diff --git a/srfi/info.rkt b/srfi/info.rkt +index c8d82de..45152e3 100644 +--- a/srfi/info.rkt ++++ b/srfi/info.rkt +@@ -3,11 +3,9 @@ + (define collection 'multi) + + (define deps '("srfi-lib" +- "srfi-doc" +- "srfi-doc-nonfree")) ++ ["srfi-doc" #:version "1.1"])) + (define implies '("srfi-lib" +- "srfi-doc" +- "srfi-doc-nonfree")) ++ "srfi-doc")) + + (define pkg-desc "Legacy SRFI (Scheme) libraries") + +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..62053500cb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,87 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) - -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Racket -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementation -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are further -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compiler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: - -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) - -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) - + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) - (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (version (package-version (racket-vm-for-system))) + (source (package-source (racket-vm-for-system))) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs (list openssl sqlite (racket-vm-for-system))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("base") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (ice-9 match)) + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key inputs configure-flags make-flags + #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each (lambda (name) + (copy-recursively + (string-append "pkgs/" name) + (string-append #$output "/lib/racket/pkgs/" name))) + '("base" "racket-lib")))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +142,77 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (list cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:phases parent-phases #~%standard-phases) + #~(modify-phases #$parent-phases + (delete 'unpack) + (replace 'build + (lambda args + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each + (match-lambda + ((name src) + (copy-recursively + src + (string-append #$output "/lib/racket/pkgs/" name)))) + '(#$@main-distribution-packages)))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -539,82 +224,900 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs "unused-untethered-bin" "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) + +(define-public main-distribution-packages + (let* ((%racket-version (package-version (racket-vm-for-system))) + (%racket-commit (string-append "v" %racket-version))) + ;; on release, commit will be %racket-commit + (append-map + (match-lambda + ((source . pkgs) + (map (match-lambda + ((? string? name) + (list name (file-append source (string-append "/" name)))) + ((name ".") + (list name source)) + ((name rel-path) + (list name (file-append source (string-append "/" rel-path))))) + pkgs))) + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,(package-source (racket-vm-for-system)) + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" "distributed-places-doc" "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" + (package-version (racket-vm-for-system))))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" "future-visualizer-pict" "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + (commit %racket-commit))) + (sha256 (base32 + "0cga4ijid6lg5j68cvdfs4xr69rsyzw7d7lixr3i866kran61sys")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/srfi/pull/15 + (search-patches "racket-srfi-fsdg-backport.patch")) + (file-name (git-file-name "racket-srfi" %racket-version))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4. 2022-02-13 21:51 ` [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-14 15:28 ` Liliana Marie Prikler 2022-02-16 20:16 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-14 15:28 UTC (permalink / raw) To: Philip McGrath, 53878 Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch, > gnu/packages/patcheches/racket-srfi-fsdg-backport.patch: New patches. > * gnu/local.mk (dist_patch_DATA): Add them. > * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): > New procedure. > * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. > Rewrite to use 'racket-vm-for-system', label-less inputs, G- > expressions, and Git origins for main-distribution packages. Separate into multiple patches. > .../patches/racket-srfi-fsdg-backport.patch | 41622 ++++++++++++++++ No. Patches should be small, not include a bunch of irrelevant doc changes. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4. 2022-02-14 15:28 ` Liliana Marie Prikler @ 2022-02-16 20:16 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-16 20:16 UTC (permalink / raw) To: Liliana Marie Prikler, 53878 Hi, On 2/14/22 10:28, Liliana Marie Prikler wrote: > Am Sonntag, dem 13.02.2022 um 16:51 -0500 schrieb Philip McGrath: >> * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch, >> gnu/packages/patcheches/racket-srfi-fsdg-backport.patch: New patches. >> * gnu/local.mk (dist_patch_DATA): Add them. >> * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): >> New procedure. >> * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. >> Rewrite to use 'racket-vm-for-system', label-less inputs, G- >> expressions, and Git origins for main-distribution packages. > Separate into multiple patches. > >> .../patches/racket-srfi-fsdg-backport.patch | 41622 ++++++++++++++++ > No. > Patches should be small, not include a bunch of irrelevant doc changes. The FSDG fix has now been applied upstream, so I can now just point at the right Git commit. Other than that, I don't know how this could reasonably be split into multiple patches. I deleted the vast majority of "gnu/packages/racket.scm" and rewrote it. Most of the work done by the old version was bootstrapping, which is now handled by the racket-vm-* packages: keeping "gnu/packages/racket.scm" nearly unchanged until this point basically was my attempt at making these changes more granularly, Even the switch to use Git origins for main-distribution packages rather than carving them out of the built tarball (which was always an ugly hack) would not be trivial to move to a separate patch. The new "racket-gui-tethered-launcher-backport.patch" (without which the 'racket' package would be broken) would have to be manually edited to apply to the built tarball---the built tarball is really not the preferred form for modifications by a long shot---and newly added packages for the new expeditor and the redesigned syntax highlighting and indentation libraries would need to be added to the old listing, only to be immediately removed. -Philip ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [RFC PATCH 9/9] gnu: racket: Update to 8.3.900. 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (6 preceding siblings ...) 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant Philip McGrath @ 2022-02-08 15:18 ` Philip McGrath 7 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-08 15:18 UTC (permalink / raw) To: 53878; +Cc: Philip McGrath * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.3.900. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 3 +- ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1549 +++++++++++------ 3 files changed, 1053 insertions(+), 525 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 94de782ca9..742e072e73 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1786,6 +1786,7 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..e3c38714c1 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,87 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) - -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Racket -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementation -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are further -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compiler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: - -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) - -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) - + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) - (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (version (package-version (racket-vm-for-system))) + (source (package-source (racket-vm-for-system))) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs (list openssl sqlite (racket-vm-for-system))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("base") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (ice-9 match)) + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key inputs configure-flags make-flags + #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each (lambda (name) + (copy-recursively + (string-append "pkgs/" name) + (string-append #$output "/lib/racket/pkgs/" name))) + '("base" "racket-lib")))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +142,77 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (list cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:phases parent-phases #~%standard-phases) + #~(modify-phases #$parent-phases + (delete 'unpack) + (replace 'build + (lambda args + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each + (match-lambda + ((name src) + (copy-recursively + src + (string-append #$output "/lib/racket/pkgs/" name)))) + '(#$@main-distribution-packages)))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -539,82 +224,898 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs "unused-untethered-bin" "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""]) + "-guix"))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) + +(define-public main-distribution-packages + (let* ((%racket-version (package-version (racket-vm-for-system))) + (%racket-commit (string-append "v" %racket-version))) + ;; on release, commit will be %racket-commit + (append-map + (match-lambda + ((source . pkgs) + (map (match-lambda + ((? string? name) + (list name (file-append source (string-append "/" name)))) + ((name ".") + (list name source)) + ((name rel-path) + (list name (file-append source (string-append "/" rel-path))))) + pkgs))) + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit "9519bb9102389fb8716703176540ba3949770b82"))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit "e9bcd18562c84eaff34f220312f102bd8db46e97"))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,(package-source (racket-vm-for-system)) + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit "0552d61f3b019167c4144fcb4e2108732d30f85c"))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit "f640064b50109887c40da6df3d3cebf635040794"))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit "a692d8ebf93ddde5f6cf3c2405b6651039afc2dc"))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit "2894fce2d5296c0eb5d7dcbf4828995941e5a476"))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit "4e75977ab091999dfd7de765e7807fabc06a6bf3"))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" "distributed-places-doc" "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit "cca0deb3ff5a570c1c3c03ea0983d106492444b7"))) + (sha256 (base32 + "1qai7sph1pyvc5j2pvwkxlzl2jgzj23s8nlfbdx74xk17i4p0xzp")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit "601bc502eda4ca2739189dd17afe6cb664f5ff53"))) + (sha256 (base32 + "183bhyhihp9rbhq6jbjxns57xxdxwf1j2ypbx6cdx5x4bhii9qk1")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit "d0550fdd1c2e5b20640f94ed99602d4e79ea20a4"))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit "6e89c54a5f9de8b925ad668888aa241722e5bbfc"))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" + (package-version (racket-vm-for-system))))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit "34973c081bdf6ffec0c69c0126d8849a00e012a3"))) + (sha256 (base32 + "0wsjisd81lhr3g1alg51v8pzwz53zfjx6c36sg7fjcza4crhk1pf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit "a3c93aeae3e3d2a421afb7269ff282c573507cd0"))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit "671d32970eef64d549a5cdbe5e3d048474c7304a"))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" "future-visualizer-pict" "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit "56d67ba04465aa19f1b3057df46bf235c79bba14"))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit "3b27c9f593e138c71ae009ad5741bf7f7282e6b3"))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit "70cc90538c5dffb722e17cabb769aeadfef32ec4"))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit "9cf89561d818be718a07c9b8f214af83a914e86c"))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit "9331d4f7169f8c5932f8d2ae721b2a96515ac895"))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit "14b164c20e1214ffa1e7585d0b6597d5c3f0351a"))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit "b3d032087d9544a0561b61fedc09adc2c63ed29d"))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit "a35720c304eafa6f9610b9ac986a89d3e0f0e889"))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit "e5bbfbeeff6f4a41e7d66b1a1c3da47bdc0d5b6b"))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit "df36b6bb46f038f6e22a19b7b9d7d061b9631600"))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit "7493795aba151f7164caf497003746dd049b8ae4"))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit "67e19384a0923ccbf2ed9e8b7ce55ff92fdefe0e"))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit "905834527683db700b87ba2b510c07aa0c688de4"))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit "14a3d57e7020e5fc65d60d20849ca6378f4d4def"))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit "b7e47a2244d848820f7eb1c80cad62b7cfdcb987"))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit "06e14b37fbd237b74563661c522df02855dadd2f"))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit "dbd6cf06613bf285b4540301ea86dd87239eab7d"))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit "399ad3351df83dee3dd2e8c4bec14ad5bcd2be8e"))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit "4f9bcab9167b690b16b79a13ce91e8ec765c00a3"))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit "d8ab4fd6f5e2f35d9738db1677dfb89e3c4ce011"))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit "9e0de9ea7204219a95d734c250afac740cb35534"))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit "cd389ba6471a045c791e2dd6e483e356017499d8"))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit "f2ce24d8e7cbefe585e3d849324b61ad2e680556"))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit "9f227e6403a07735765a57ff521d5f78588543c6"))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit "350f5da48d98303fe6ee510892c958ed46766154"))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit "6da78b761a6005fdfe771318097513adf38c9564"))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit "8e683244eea9dd5526324529f972947f7111810f"))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit "a9fc521dbeb859ea6683cee4a83ed24d1e15ca12"))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit "24912978e7b104449e801cf0a8469b8f363aa170"))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit "26ca7fc5a03cc7ae797e9269444d97e6728a1b0d"))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit "f4d66a2c31749e3795722092b0a9d4fa698c2992"))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit "6e79a13b9e24969a87c8a1c191d38ee4f4c55cf9"))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit "4bad4b9e9bcc363df453ae5e4211641cddc29e4b"))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit "6c04ee267d258a13f9c5cbc437dac60234e54ef4"))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit "df55a811d57d6677959fde479106bc43b99d6bdd"))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit "81afce5b4c4fc3e9a06e813b888d7c8ea10b6a32"))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit "85446b0caf8560c30d7e2ed9c23104bf20b27ae6"))) + (sha256 (base32 + "1jv0b043ppph75bjzfdc0jibgpig34lnsbksxnqz03pmv3yxp6cr")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit "3fd78eb8a0ba7ad86d8f78e866d737b177144729"))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit "408f9398ec237b791ca103bb9e1400df1cef18f5"))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit "d2d820bdedf7ec4971ed03e9a0adcfb5f71ed1fa"))) + (sha256 (base32 + "15rhf4lhrwqab9vdq42mf227ialm6yi5q8hxsb4kw4yq6dks4xcd")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" "scribble-doc" "scribble-html-lib" "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit "cabf4188a34c70af2f6a376fc3b0f55d035a2ab7"))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit "d1906923a74a362a2bfb32f3b9bfe1351f4d1534"))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit "3bc582e4167a46ade43dfd50df06a2e6e08e90ab"))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit "06bbcd3651e518a53cffa5f8484fe127574fed06"))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit "e8b2471aaafef035e12e641dd34226f36a9ca16a"))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit "d553e3bd27c866cb93d5144c0f07e4024827167b"))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit "4b07b7b6cab5c08b5b589d3f501376fc0a2b935d"))) + (sha256 (base32 + "0vvy7byynbk7rx2a0cr3ky2ifgmhcrw22xyiibd4c4knqqkdcmc7")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + ;;(url "https://github.com/racket/srfi") + (url "https://github.com/LiberalArtist/srfi") + ;; FSDG fix for SRFI 5: + ;; see https://github.com/racket/srfi/pull/15 and + ;; https://lists.gnu.org/archive/html/guix-devel/2022-01/msg00426.html + ;; (Probably can be merged upstream before we update to 8.4.) + (commit "8de2fb2c566f285ee3fc14bad15d74e21de014cd"))) + (sha256 (base32 + "07xi9pdg5sqcy1njppmqaaigrf054d6h74wfcwq5ikg2kjgc0d5w")) + (file-name (git-file-name "racket-srfi" %racket-version))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit "90fdb2613beaefe57fa0305fe90e635e2b8a8f57"))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit "122e38efb9842394ef6462053991efb4bd0edf3b"))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit "c3ba4e86790946ed77192b541f49930e5861619d"))) + (sha256 (base32 + "1dwl0v2ghdyyk5x5rw20il192wrq9myijz98dfncy5cz0hqlm25f")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit "7878c9ed33da27810a55d8bdd603f56dd4c89fb7"))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit "698eade65ae2cd8b747ba08a3820950e385b2a81"))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit "655676cdebe6d6223935ec5b288d574639ced431"))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit "555a380a63e63977fec77c4063d58f6bdf646249"))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit "3f3d7c2619ca73df982dc1dc67ed8040709b6d38"))) + (sha256 (base32 + "1sw0g0cnkq6xc8x8i2mfz7qkimrv1c7gbhqfkm0zwafzi2zbvbh7")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (14 more replies) 2022-02-19 22:34 ` [bug#53878] Fwd: Re: [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath ` (2 subsequent siblings) 4 siblings, 15 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun Hi, As promised, here is v3! Changes since v2: * 05/15: Fix typo in commit message. * 09/15: Add `%racket-version` and `%racket-origin`. * 11/15: Add `%chez-scheme-for-racket-version`. * 15/15: Use `%racket-version` and `%racket-origin`. Also: * `racket-minimal`: The package to install explicitly is "racket-lib" ("base" is implicit). * `make-installation-layer.rkt`: Adjust workaround for <https://github.com/racket/racket/issues/4133>, because `racket` (but not `racket-minimal`) ends up actually creating the bogus untethered "bin" directory. I've also put these patches up at <https://gitlab.com/philip1/guix-patches/-/tags/guix-issue-53878-v3> -Philip Philip McGrath (15): gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: Add racket-vm-cgc. gnu: Add racket-vm-bc. gnu: Add chez-scheme-for-racket. gnu: Add racket-vm-cs. gnu: chez-mit: Support chez-scheme-for-racket. gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. gnu: racket: Update to 8.4. gnu/local.mk | 5 +- gnu/packages/chez-and-racket-bootstrap.scm | 1074 ++++++++++++ gnu/packages/chez.scm | 628 +++---- gnu/packages/emacs-xyz.scm | 4 +- gnu/packages/loko.scm | 4 +- .../racket-enable-scheme-backport.patch | 465 +++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1557 +++++++++++------ 8 files changed, 2821 insertions(+), 942 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (13 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. * gnu/packages/loko.scm: Likewise. * gnu/packages/racket.scm: Likewise. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 278 +++++++++++++++++++++ gnu/packages/chez.scm | 225 +---------------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- gnu/packages/racket.scm | 2 +- 6 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm diff --git a/gnu/local.mk b/gnu/local.mk index 7e781d8126..d963625a63 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -144,6 +144,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/certs.scm \ %D%/packages/check.scm \ %D%/packages/chemistry.scm \ + %D%/packages/chez-and-racket-bootstrap.scm \ %D%/packages/chez.scm \ %D%/packages/chicken.scm \ %D%/packages/chromium.scm \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm new file mode 100644 index 0000000000..f102b099fb --- /dev/null +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch> +;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> +;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> +;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages chez-and-racket-bootstrap) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix utils) + #:use-module (guix gexp) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages compression) + #:use-module (gnu packages ghostscript) + #:use-module (gnu packages linux) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages netpbm) + #:use-module (gnu packages tex) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +;; Commentary: +;; +;; Alphabetically and chronologically, Chez comes before Racket. +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Putting the relevant definitions together in this module avoids having to +;; work around dependency cycles. +;; +;; Code: + +(define nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +(define stex + ;; This commit includes a fix, which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (version "1.2.2") + (version (git-version version "1" commit))) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name "stex" version))))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version "9.5.6") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet + ;; Remove bundled libraries. + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))))))) + (build-system gnu-build-system) + (inputs + `(("libuuid" ,util-linux "lib") + ("zlib" ,zlib) + ("zlib:static" ,zlib "static") + ("lz4" ,lz4) + ("lz4:static" ,lz4 "static") + ;; for expeditor: + ("ncurses" ,ncurses) + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + ("libx11" ,libx11))) + (native-inputs + `(("nanopass" ,nanopass) ; source only + ;; for docs + ("stex" ,stex) + ("xorg-rgb" ,xorg-rgb) + ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek))) + ("ghostscript" ,ghostscript) + ("netpbm" ,netpbm))) + (native-search-paths + (list (search-path-specification + (variable "CHEZSCHEMELIBDIRS") + (files (list (string-append "lib/csv" version "-site")))))) + (outputs '("out" "doc")) + (arguments + `(#:modules + ((guix build gnu-build-system) + (guix build utils) + (ice-9 ftw) + (ice-9 match)) + #:test-target "test" + #:configure-flags + '("--threads") ;; TODO when we fix armhf, it doesn't support --threads + #:phases + (modify-phases %standard-phases + ;; put these where configure expects them to be + (add-after 'unpack 'unpack-nanopass+stex + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (for-each (lambda (dep) + (define src + (assoc-ref (or native-inputs inputs) dep)) + (copy-recursively src dep + #:keep-mtime? #t)) + '("nanopass" "stex")))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs outputs + (configure-flags '()) + #:allow-other-keys) + (let* ((zlib-static (assoc-ref inputs "zlib:static")) + (lz4-static (assoc-ref inputs "lz4:static")) + (out (assoc-ref outputs "out")) + ;; add flags which are always required: + (flags (cons* + (string-append "--installprefix=" out) + (string-append "ZLIB=" zlib-static "/lib/libz.a") + (string-append "LZ4=" lz4-static "/lib/liblz4.a") + ;; Guix will do compress man pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" ,(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke + "./configure" + flags)))) + ;; The binary file name is called "scheme" as is the one from MIT/GNU + ;; Scheme. We add a symlink to use in case both are installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bin (string-append out "/bin")) + (lib (string-append out "/lib")) + (name "chez-scheme")) + (symlink (string-append bin "/scheme") + (string-append bin "/" name)) + (map (lambda (file) + (symlink file (string-append (dirname file) + "/" name ".boot"))) + (find-files lib "scheme.boot"))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (stex-output "/tmp") + (doc-dir (string-append stex-output + "/share/doc/" + stex+version))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/" + stex+version) + (string-append "Scheme=" + (assoc-ref outputs "out") + "/bin/scheme")) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((chez+version (strip-store-file-name + (assoc-ref outputs "out"))) + (stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + (scheme (string-append (assoc-ref outputs "out") + "/bin/scheme")) + ;; see note on stex-output in phase build-stex, above: + (stexlib (string-append "/tmp" + "/lib/" + stex+version)) + (doc-dir (string-append (assoc-ref outputs "doc") + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" + "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))) + ;; Chez Scheme does not have a MIPS backend. + ;; FIXME: Debian backports patches to get armhf working. + ;; We should too. It is the Chez machine type arm32le + ;; (no threaded version upstream yet, though there is in + ;; Racket's fork), more specifically (per the release notes) ARMv6. + (supported-systems (fold delete %supported-systems + '("mips64el-linux" "armhf-linux"))) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "R6RS Scheme compiler and run-time") + (description + "Chez Scheme is a compiler and run-time system for the language of the +Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler +generates native code for each target processor, with support for x86, x86_64, +and 32-bit PowerPC architectures.") + (license license:asl2.0))) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..caf61a95f5 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -4,7 +4,6 @@ ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,234 +31,12 @@ (define-module (gnu packages chez) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (guix build-system gnu) - #:use-module (gnu packages compression) - #:use-module (gnu packages ncurses) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages ghostscript) - #:use-module (gnu packages linux) - #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) - #:use-module (gnu packages compression) - #:use-module (gnu packages image) - #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - -(define-public chez-scheme - (package - (name "chez-scheme") - (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) - (build-system gnu-build-system) - (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) - (native-search-paths - (list (search-path-specification - (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) - (outputs '("out" "doc")) - (arguments - `(#:modules - ((guix build gnu-build-system) - (guix build utils) - (ice-9 ftw) - (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) - ;; Chez Scheme does not have a MIPS backend. - ;; FIXME: Debian backports patches to get armhf working. - ;; We should too. It is the Chez machine type arm32le - ;; (no threaded version upstream yet, though there is in - ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) - (home-page "https://cisco.github.io/ChezScheme/") - (synopsis "R6RS Scheme compiler and run-time") - (description - "Chez Scheme is a compiler and run-time system for the language of the -Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler -generates native code for each target processor, with support for x86, x86_64, -and 32-bit PowerPC architectures.") - (license asl2.0))) - (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 50232fcbbc..cb7d4425af 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -145,7 +145,7 @@ (define-module (gnu packages emacs-xyz) #:use-module (gnu packages aspell) #:use-module (gnu packages audio) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages cmake) #:use-module (gnu packages code) #:use-module (gnu packages cpp) diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..74a649b8a1 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -24,7 +24,7 @@ (define-module (gnu packages loko) #:use-module (gnu packages package-management) #:use-module (gnu packages guile) #:use-module (gnu packages guile-xyz) - #:use-module (gnu packages chez)) + #:use-module (gnu packages chez-and-racket-bootstrap)) (define-public loko-scheme (package diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..865fdff70f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -34,7 +34,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages compression) #:use-module (gnu packages databases) #:use-module (gnu packages fontutils) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (12 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". * gnu/packages/chez.scm (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez-and-racket-bootstrap.scm | 2 +- gnu/packages/chez.scm | 373 +++++++++++---------- 2 files changed, 191 insertions(+), 184 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f102b099fb..1ed4631ced 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -136,7 +136,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index caf61a95f5..54bbee7923 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -37,6 +37,28 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) + +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -54,13 +76,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -85,42 +105,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -144,95 +170,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -253,10 +258,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -284,10 +290,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -314,17 +321,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -354,10 +362,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -386,46 +395,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) (with-directory-excursion (dirname mk-file) (apply invoke "make" "build" make-flags))))) (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 03/15] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath ` (11 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez-and-racket-bootstrap (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1ed4631ced..11d570059b 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -114,9 +114,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -169,14 +167,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 05/15] gnu: chez-scheme: Use new package style Philip McGrath ` (10 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New private functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. --- gnu/packages/chez-and-racket-bootstrap.scm | 118 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 11d570059b..1a923fe62d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -28,7 +28,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (ice-9 match) + #:use-module (ice-9 regex) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -61,6 +63,115 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; + (define nanopass (let ((version "1.9.2")) (origin @@ -264,8 +375,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 05/15] gnu: chez-scheme: Use new package style. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 06/15] gnu: Add stex Philip McGrath ` (9 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass, stex): Make public as a temporary workaround for Racket. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 288 ++++++++++----------- gnu/packages/racket.scm | 5 +- 2 files changed, 137 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1a923fe62d..81ac8f0774 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -172,7 +172,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -182,7 +182,7 @@ (define nanopass (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) (file-name (git-file-name "nanopass" version))))) -(define stex +(define-public stex ;; This commit includes a fix, which we would otherwise want to use as ;; patch. Let's revert to tagged releases as soon as one becomes available. (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") @@ -199,86 +199,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -286,90 +280,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 865fdff70f..a1ba57cca3 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) + ("stex" ,stex) + ("nanopass" ,nanopass))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 06/15] gnu: Add stex. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 05/15] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 07/15] gnu: Add chez-nanopass Philip McGrath ` (8 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap'. (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 215 +++++++++++++++------ gnu/packages/racket.scm | 2 +- 2 files changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 81ac8f0774..83bf15b5fb 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -31,6 +31,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -172,30 +173,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define-public stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -232,15 +209,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -263,9 +232,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -301,32 +272,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -334,7 +282,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -370,3 +320,146 @@ (define* (stex-make #:optional (suffix "")) generates native code for each target processor, with support for x86, x86_64, and 32-bit PowerPC architectures.") (license license:asl2.0))) + +;; +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license license:expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a1ba57cca3..d8338bcd6f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,7 +333,7 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,stex) + ("stex" ,(package-source stex)) ("nanopass" ,nanopass))) (arguments `(#:phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 07/15] gnu: Add chez-nanopass. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 06/15] gnu: Add stex Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (7 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex'. (chez-nanopass): New variable. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Adapt accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 96 ++++++++++++++++++---- gnu/packages/racket.scm | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 83bf15b5fb..d66955d50d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -207,9 +207,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -228,10 +226,12 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (copy-recursively + (dirname (search-input-file (or native-inputs inputs) + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) (mkdir-p "stex") (with-output-to-file "stex/Mf-stex" (lambda () @@ -454,12 +454,76 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license license:expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d8338bcd6f..e8d016c07b 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -334,7 +334,7 @@ (define-public racket-bootstrap-chez-bootfiles racket-minimal racket-minimal-bc-3m)) ("stex" ,(package-source stex)) - ("nanopass" ,nanopass))) + ("nanopass" ,(package-source chez-nanopass)))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 07/15] gnu: Add chez-nanopass Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath ` (6 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun This might seem a bit silly in isolation, but it makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. --- gnu/packages/chez-and-racket-bootstrap.scm | 51 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index d66955d50d..366815634d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -187,7 +187,7 @@ (define-public chez-scheme (sha256 (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) + (file-name (git-file-name "chez-scheme" version)) (snippet #~(begin (use-modules (guix build utils)) (for-each (lambda (dir) @@ -207,7 +207,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -237,6 +239,14 @@ (define-public chez-scheme (lambda () ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -321,6 +331,43 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license license:asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 20:46 ` Liliana Marie Prikler 2022-02-19 6:42 ` [bug#53878] [PATCH v3 10/15] gnu: Add racket-vm-bc Philip McGrath ` (5 subsequent siblings) 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/patches/racket-enable-scheme-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez-submodules, %racket-version, %racket-origin, racket-vm-cgc): New variables. (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 320 +++++++++++- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ 3 files changed, 776 insertions(+), 10 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index d963625a63..3a6a4a48b3 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1751,6 +1751,7 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 366815634d..5eedd9a11f 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -34,15 +34,20 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) + #:use-module (gnu packages autotools) + #:use-module (gnu packages bash) #:use-module (gnu packages compression) #:use-module (gnu packages ghostscript) + #:use-module (gnu packages libffi) #:use-module (gnu packages linux) #:use-module (gnu packages ncurses) #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) #:use-module (gnu packages xorg) #:use-module ((guix licenses) - #:prefix license:)) + #:prefix license:) + #:export (%racket-version + %racket-origin)) ;; Commentary: ;; @@ -62,6 +67,136 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; Putting the relevant definitions together in this module avoids having to ;; work around dependency cycles. ;; +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: +;; +;; - Racket BC [CGC] can be built with only a C compiler (except for +;; one caveat discussed below). +;; - Racket BC [3M] needs an existing Racket to run "xform", +;; which transforms its own C source code to add additional annotations +;; for the precise garbage collector. +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. +;; It also needs an existing Racket to compile Racket-implemented +;; parts of the runtime system to R6RS libraries. +;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate +;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler +;; purely from source into Racket and apply the compiler to itself, +;; producing the needed bootfiles (albeit very slowly). +;; Any variant of Racket since version 7.1 can run the simulation. +;; +;; So, we build CGC to build 3M to build bootfiles and CS. +;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; +;; One remaining bootstrapping limitation is that Racket's reader, module +;; system, and macro expander are implemented in Racket. For Racket CS, +;; they are compiled to R6RS libraries as discussed above. This note from the +;; README file applies to all such subsystems: +;; +;; The Racket version must be practically the same as the current Racket +;; verson, although it can be the Racket BC implementation (instead of +;; the Racket CS implementation). +;; +;; Unlike Chez Scheme boot files, the files generated in "schemified" +;; are human-readable and -editable Scheme code. That provides a way +;; out of bootstrapping black holes, even without BC. +;; +;; However, other Racket subsystems implemented in Racket for Racket CS +;; use older C implementations for Racket BC, whereas the reader, expander, +;; and module system were completely replaced with the Racket implementation +;; +;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) +;; are embeded in C as a static string constant. Eventually, they are further +;; compiled by the C-implemented Racket BC bytecode and JIT compilers. +;; (On platforms where Racket BC's JIT is not supported, yet another compiler +;; instead compiles the linklets to C code, but this is not a bootstrapping +;; issue.) +;; ;; Code: (define (chez-machine->nonthreaded machine) @@ -169,6 +304,179 @@ (define* (chez-upstream-features-for-system #:optional (else '(threads)))) +;; +;; Chez auxiliary G-expressions: +;; + +(define unbundle-chez-submodules + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) + +;; +;; Racket VM: +;; + +(define %racket-version "8.4") +(define %racket-origin + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit (string-append "v" %racket-version)))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" %racket-version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + #$unbundle-chez-submodules) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + +(define (racket-vm-common-configure-flags) + ;; under a lambda extraction to avoid evaluating bash-minimal too early + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip" + "--enable-origtree")) + +(define-public racket-vm-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-vm-cgc") + (version %racket-version) + (source %racket-origin) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants + (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") + #:phases + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + ;; ;; Chez Scheme: ;; @@ -188,15 +496,7 @@ (define-public chez-scheme (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) (file-name (git-file-name "chez-scheme" version)) - (snippet #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib")))))) + (snippet unbundle-chez-submodules))) (build-system gnu-build-system) (inputs (list diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-19 20:46 ` Liliana Marie Prikler [not found] ` <2223439.vW7IG60toP@bastet> 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-19 20:46 UTC (permalink / raw) To: Philip McGrath, 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-enable-scheme-backport.patch: New > patch. > * gnu/local.mk (dist_patch_DATA): Add it. > * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez- > submodules, > %racket-version, %racket-origin, racket-vm-cgc): New variables. > (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. Something weird happened to me just now trying to build this series. While compiling emacs-xyz, an error was raised regarding %racket- version not existing and and import being missing. Assuming that you didn't mess up an include somewhere, there could be a cycle meaning we'd have to pass the version and origin by function as I originally said in my reply to v2. I'll clean up my work tree and try to reapply it, but that will take some time. Since you mentioned re-exports causing issues, I'd like to ask if you've made a similar experience, but the results got somehow hidden after the right incantations. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
[parent not found: <2223439.vW7IG60toP@bastet>]
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. [not found] ` <2223439.vW7IG60toP@bastet> @ 2022-02-20 9:03 ` Liliana Marie Prikler 2022-02-20 14:09 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-20 9:03 UTC (permalink / raw) To: Philip McGrath; +Cc: 53878 Am Samstag, dem 19.02.2022 um 17:27 -0500 schrieb Philip McGrath: > Hi, > > On Saturday, February 19, 2022 3:46:47 PM EST you wrote: > > Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > > > * gnu/packages/patches/racket-enable-scheme-backport.patch: New > > > patch. > > > * gnu/local.mk (dist_patch_DATA): Add it. > > > * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez- > > > submodules, > > > %racket-version, %racket-origin, racket-vm-cgc): New variables. > > > (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. > > > > Something weird happened to me just now trying to build this > > series. While compiling emacs-xyz, an error was raised regarding > > %racket-version not existing and and import being missing. > > Assuming that you didn't mess up an include somewhere, there could > > be a cycle meaning we'd have to pass the version and origin by > > function as I originally said in my reply to v2. > > > > I'll clean up my work tree and try to reapply it, but that will > > take some time. Since you mentioned re-exports causing issues, I'd > > like to ask if you've made a similar experience, but the results > > got somehow hidden after the right incantations. > > I haven't seen errors from emacs-xyz, but I have gotten errors about > %racket-version not existing: at the time I thought it was just a > problem with incremental rebuilds while moving back and forward > through history, but, having just refreshed my memory on more details > of the cyclic issues, I think it may be related. I'll send another > email presently with details once I've gathered references. > > For now, I found that `rm gnu/packages/*.go` was enough to get `make` > to succeed again. As you said, the clean build succeeds, but I still think we should do something about incremental rebuilds. So here's my suggestion: Inside chez-and-racket-bootstrap, define (make-<package>) functions for the following: - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: Taking version and origin. - racket-vm-cgc: Taking version and origin. - racket-vm-bc: Taking racket-vm-cgc. - racket-vm-cs: Taking racket-vm-bc. Inside chez, define chez-scheme, as well as non-bootstrapped versions of stex et al. Also define make-chez-scheme-for-racket, taking version and origin as parameter. Finally, define chez-scheme-for-system, which uses (resolve-interface '(gnu packages racket)) to get racket's version and origin. Inside racket, define %racket-version, %racket-origin, racket-minimal and racket. It'd also be good if you made local definitions (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- origin)) (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) ... in this file. With this split, it should be possible to do incremental builds without stuff breaking. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-20 9:03 ` Liliana Marie Prikler @ 2022-02-20 14:09 ` Philip McGrath 2022-02-20 16:48 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-20 14:09 UTC (permalink / raw) To: Liliana Marie Prikler; +Cc: 53878 [-- Attachment #1: Type: text/plain, Size: 2354 bytes --] Hi, On Sunday, February 20, 2022 4:03:26 AM EST Liliana Marie Prikler wrote: > So here's my suggestion: > > Inside chez-and-racket-bootstrap, define (make-<package>) functions for > the following: > - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: > Taking version and origin. > - racket-vm-cgc: Taking version and origin. > - racket-vm-bc: Taking racket-vm-cgc. > - racket-vm-cs: Taking racket-vm-bc. > > Inside chez, define chez-scheme, as well as non-bootstrapped versions > of stex et al. > Also define make-chez-scheme-for-racket, taking version and origin as > parameter. Finally, define chez-scheme-for-system, which uses > (resolve-interface '(gnu packages racket)) to get racket's version and > origin. > > Inside racket, define %racket-version, %racket-origin, racket-minimal > and racket. It'd also be good if you made local definitions > (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- > origin)) > (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) > ... > in this file. My understanding—which is not very good!—is that this would have the same problem we do currently. It would be analogous to my example from <https://issues.guix.gnu.org/53878#93>: > But Ludo’'s examples show that's wrong: those uses of `chez scheme` are in > what the "expansion contexts" model would call "expression contexts". > > Instead, I think rule № 2 prohibits any reference to a variable imported > from > another (gnu packages ...) module that will be evaluated when the (gnu > packages ...) modules are—visited? instantiated? [2][3]—IDK when exactly, > but, for practical purposes, any variable reference that is not underneath > a lambda abstraction. > > If that's right, IIUC, it would mean that: > > (define chez-scheme-for-racket > (make-chez-scheme-for-racket ...)) > > would also be prohibited. > > On the other hand, uses of `(racket-vm-for-system)` and `(chez-scheme-for- > system)` in an `imports` field should still be fine, thanks to the implicit > thunks. The reference to `make-chez-scheme-for-racket` or `make-racket-vm-cs` or any such procedure defined in "chez-and-racket-bootstrap.scm" would be evaluated when "racket.scm" is instantiated—or whenever precisely it is that causes the problem. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-20 14:09 ` Philip McGrath @ 2022-02-20 16:48 ` Liliana Marie Prikler 2022-02-20 17:52 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-20 16:48 UTC (permalink / raw) To: Philip McGrath; +Cc: 53878 Am Sonntag, dem 20.02.2022 um 09:09 -0500 schrieb Philip McGrath: > Hi, > > On Sunday, February 20, 2022 4:03:26 AM EST Liliana Marie Prikler > wrote: > > So here's my suggestion: > > > > Inside chez-and-racket-bootstrap, define (make-<package>) functions > > for > > the following: > > - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: > > Taking version and origin. > > - racket-vm-cgc: Taking version and origin. > > - racket-vm-bc: Taking racket-vm-cgc. > > - racket-vm-cs: Taking racket-vm-bc. > > > > Inside chez, define chez-scheme, as well as non-bootstrapped > > versions of stex et al. Also define make-chez-scheme-for-racket, > > taking version and origin as parameter. Finally, define chez- > > scheme-for-system, which uses (resolve-interface '(gnu packages > > racket)) to get racket's version and > > origin. > > > > Inside racket, define %racket-version, %racket-origin, racket- > > minimal > > and racket. It'd also be good if you made local definitions > > (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- > > origin)) > > (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) > > ... > > in this file. > > My understanding—which is not very good!—is that this would have the > same problem we do currently. It would be analogous to my example > from <https://issues.guix.gnu.org/53878#93>: Well, for one this claim is both verifiable and falsifiable by way of implementation. For another, I don't really see the issue however. Since those bindings would be local to racket.scm and not used anywhere else, I don't think there is a cycle to be found anywhere. > > > But Ludo’'s examples show that's wrong: those uses of `chez > > scheme` are in what the "expansion contexts" model would call > > "expression contexts". > > > > Instead, I think rule № 2 prohibits any reference to a variable > > imported from another (gnu packages ...) module that will be > > evaluated when the (gnu packages ...) modules are—visited? > > instantiated? [2][3]—IDK when exactly, but, for practical purposes, > > any variable reference that is not underneath a lambda abstraction. > > > > If that's right, IIUC, it would mean that: > > > > (define chez-scheme-for-racket > > (make-chez-scheme-for-racket ...)) > > > > would also be prohibited. > > > > On the other hand, uses of `(racket-vm-for-system)` and `(chez- > > scheme-for-system)` in an `imports` field should still be fine, > > thanks to the implicit thunks. > The reference to `make-chez-scheme-for-racket` or `make-racket-vm-cs` > or any such procedure defined in "chez-and-racket-bootstrap.scm" > would be evaluated when "racket.scm" is instantiated—or whenever > precisely it is that causes the problem. I don't think that'd be a problem since make-chez-scheme-for-racket is itself a function. If it still is, one pair of brackets makes it not so. This is a well-explored technique of resolving chains, used for example in our build system code. chez-and-racket-bootstrap.scm should imo not be imported anywhere but chez.scm and racket.scm, so it by itself can not form a cycle. Only chez.scm and racket.scm can, but there are ways of making those well-formed. See (standard-packages) in guix/build-system/gnu.scm pointing to (gnu packages commencement) or (default-python) in guix/build- system/python.scm for pointers. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-20 16:48 ` Liliana Marie Prikler @ 2022-02-20 17:52 ` Philip McGrath 2022-02-20 18:13 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-20 17:52 UTC (permalink / raw) To: Liliana Marie Prikler, 53878, Ludovic Courtès Cc: Attila Lendvai, Maxime Devos, Malte Gerdes, raingloom, zimoun [-- Attachment #1: Type: text/plain, Size: 5202 bytes --] Hi, On Sunday, February 20, 2022 11:48:01 AM EST Liliana Marie Prikler wrote: > Am Sonntag, dem 20.02.2022 um 09:09 -0500 schrieb Philip McGrath: > > Hi, > > > > On Sunday, February 20, 2022 4:03:26 AM EST Liliana Marie Prikler > > > > wrote: > > > So here's my suggestion: > > > > > > Inside chez-and-racket-bootstrap, define (make-<package>) functions > > > for > > > the following: > > > - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: > > > Taking version and origin. > > > - racket-vm-cgc: Taking version and origin. > > > - racket-vm-bc: Taking racket-vm-cgc. > > > - racket-vm-cs: Taking racket-vm-bc. > > > > > > Inside chez, define chez-scheme, as well as non-bootstrapped > > > versions of stex et al. Also define make-chez-scheme-for-racket, > > > taking version and origin as parameter. Finally, define chez- > > > scheme-for-system, which uses (resolve-interface '(gnu packages > > > racket)) to get racket's version and > > > origin. > > > > > > Inside racket, define %racket-version, %racket-origin, racket- > > > minimal > > > and racket. It'd also be good if you made local definitions > > > (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- > > > origin)) > > > (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) > > > ... > > > in this file. > > > > My understanding—which is not very good!—is that this would have the > > same problem we do currently. It would be analogous to my example > > > from <https://issues.guix.gnu.org/53878#93>: > Well, for one this claim is both verifiable and falsifiable by way of > implementation. For another, I don't really see the issue however. > Since those bindings would be local to racket.scm and not used anywhere > else, I don't think there is a cycle to be found anywhere. > While working on v4, I did try using `racket-vm-for-system` at what Ludo’ called "the top level of a module", and I encountered the same error. > > > But Ludo’'s examples show that's wrong: those uses of `chez > > > scheme` are in what the "expansion contexts" model would call > > > "expression contexts". > > > > > > Instead, I think rule № 2 prohibits any reference to a variable > > > imported from another (gnu packages ...) module that will be > > > evaluated when the (gnu packages ...) modules are—visited? > > > instantiated? [2][3]—IDK when exactly, but, for practical purposes, > > > any variable reference that is not underneath a lambda abstraction. > > > > > > If that's right, IIUC, it would mean that: > > > > > > (define chez-scheme-for-racket > > > (make-chez-scheme-for-racket ...)) > > > > > > would also be prohibited. > > > > > > On the other hand, uses of `(racket-vm-for-system)` and `(chez- > > > scheme-for-system)` in an `imports` field should still be fine, > > > thanks to the implicit thunks. > > > > The reference to `make-chez-scheme-for-racket` or `make-racket-vm-cs` > > or any such procedure defined in "chez-and-racket-bootstrap.scm" > > would be evaluated when "racket.scm" is instantiated—or whenever > > precisely it is that causes the problem. > > I don't think that'd be a problem since make-chez-scheme-for-racket is > itself a function. If it still is, one pair of brackets makes it not > so. This is a well-explored technique of resolving chains, used for > example in our build system code. chez-and-racket-bootstrap.scm should > imo not be imported anywhere but chez.scm and racket.scm, so it by > itself can not form a cycle. Only chez.scm and racket.scm can, but > there are ways of making those well-formed. AFAICT the error is not from applying the function bound to the variable `racket-vm-for-system` (or `make-racket-vm-bc`, or whatever), but from evaluating the reference to a variable imported from a sibling `(gnu packages ...)` module, regardless of the value to which the variable is bound. My current best guess at Guile's semantics for mutually-recursive modules is that it's something like the `letrec` restriction, e.g. the difference between these two examples (given an implementation that fully enforces `letrec` semantics, as opposed to `letrec*`): --8<---------------cut here---------------start------------->8--- $ scheme Chez Scheme Version 9.5.6 Copyright 1984-2021 Cisco Systems, Inc. > (letrec ((a (lambda () 1)) (b a)) 2) Exception: attempt to reference undefined variable a Type (debug) to enter the debugger. > (letrec ((a (lambda () 1)) (b (lambda () (a)))) (b)) 1 --8<---------------cut here---------------end--------------->8--- > > See (standard-packages) in guix/build-system/gnu.scm pointing to (gnu > packages commencement) or (default-python) in guix/build- > system/python.scm for pointers. Given Ludo’'s explanation, I think the difference (or at least an important difference) is that those functions are defined in `(guix ...)` modules, as opposed to `(gnu packages ...)` modules. But I wish I knew with any degree of certainty *why* this would be true, if indeed it is. Maybe Maxime knows? -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-20 17:52 ` Philip McGrath @ 2022-02-20 18:13 ` Liliana Marie Prikler 2022-02-23 18:55 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-20 18:13 UTC (permalink / raw) To: Philip McGrath, 53878, Ludovic Courtès Cc: Attila Lendvai, Maxime Devos, Malte Gerdes, raingloom, zimoun Hi, Am Sonntag, dem 20.02.2022 um 12:52 -0500 schrieb Philip McGrath: > AFAICT the error is not from applying the function bound to the > variable `racket-vm-for-system` (or `make-racket-vm-bc`, or > whatever), but from evaluating the reference to a variable imported > from a sibling `(gnu packages ...)` module, regardless of the value > to which the variable is bound. > > My current best guess at Guile's semantics for mutually-recursive > modules is that it's something like the `letrec` restriction, e.g. > the difference between these two examples (given an implementation > that fully enforces `letrec` semantics, as opposed to `letrec*`): > > --8<---------------cut here---------------start------------->8--- > $ scheme > Chez Scheme Version 9.5.6 > Copyright 1984-2021 Cisco Systems, Inc. > > > (letrec ((a (lambda () 1)) > (b a)) > 2) > Exception: attempt to reference undefined variable a > Type (debug) to enter the debugger. > > (letrec ((a (lambda () 1)) > (b (lambda () (a)))) > (b)) > 1 > --8<---------------cut here---------------end--------------->8--- > > > > > See (standard-packages) in guix/build-system/gnu.scm pointing to > > (gnu > > packages commencement) or (default-python) in guix/build- > > system/python.scm for pointers. > > Given Ludo’'s explanation, I think the difference (or at least an > important difference) is that those functions are defined in `(guix > ...)` modules, as opposed to `(gnu packages ...)` modules. > > But I wish I knew with any degree of certainty *why* this would be > true, if indeed it is. > > Maybe Maxime knows? Both Ludo and Maxime already explained this, but to be extra clear, it's the thunking. (define foo <something-in-bar.scm>) (define bar <something-in-foo.scm>) <- problem (define (foo) <something-in-bar.scm>) (define bar <something-in-foo.scm>) <- no problem. Since inputs are thunked, you can define chez in chez.scm and racket in racket.scm and use them as input to each other without breaking the compiler (you will break the package builder though). If you want something more meaningful, you can define racket-minimal in racket.scm and use it in chez.scm as input to a package, then use that package as input to racket. This does not work for (source ) and (inherit ) however, because those forms are not thunked. You would have to thunk them until you reach a save haven (like a package's inputs), where you can call the thunk to produce a value. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-20 18:13 ` Liliana Marie Prikler @ 2022-02-23 18:55 ` Philip McGrath 2022-02-23 20:31 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-23 18:55 UTC (permalink / raw) To: Liliana Marie Prikler, Philip McGrath, 53878, Ludovic Courtès Cc: Attila Lendvai, Maxime Devos, Malte Gerdes, raingloom, zimoun Hi, On 2/20/22 13:13, Liliana Marie Prikler wrote: >> Given Ludo’'s explanation, I think the difference (or at least an >> important difference) is that those functions are defined in `(guix >> ...)` modules, as opposed to `(gnu packages ...)` modules. >> >> But I wish I knew with any degree of certainty *why* this would be >> true, if indeed it is. >> >> Maybe Maxime knows? > Both Ludo and Maxime already explained this, but to be extra clear, > it's the thunking. > > (define foo <something-in-bar.scm>) > (define bar <something-in-foo.scm>) <- problem > > (define (foo) <something-in-bar.scm>) > (define bar <something-in-foo.scm>) <- no problem. > > Since inputs are thunked, you can define chez in chez.scm and racket in > racket.scm and use them as input to each other without breaking the > compiler (you will break the package builder though). If you want > something more meaningful, you can define racket-minimal in racket.scm > and use it in chez.scm as input to a package, then use that package as > input to racket. This does not work for (source ) and (inherit ) > however, because those forms are not thunked. You would have to thunk > them until you reach a save haven (like a package's inputs), where you > can call the thunk to produce a value. To try to be concrete, I made the patch below as a mock-up of part of your earlier suggestion (IIUC): On 2/20/22 04:03, Liliana Marie Prikler wrote: > Inside chez-and-racket-bootstrap, define (make-<package>) functions for > the following: > - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: > Taking version and origin. > - racket-vm-cgc: Taking version and origin. > - racket-vm-bc: Taking racket-vm-cgc. > - racket-vm-cs: Taking racket-vm-bc. > ... > > Inside racket, define %racket-version, %racket-origin, racket-minimal > and racket. It'd also be good if you made local definitions > (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- > origin)) > (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) > ... > in this file. This applies on top of v4, or I've put it at <https://gitlab.com/philip1/guix-patches/-/commit/982fe7cfb4d33103ee611acc310e3225ccf35852> if that's easier for anyone: --8<---------------cut here---------------start------------->8--- From 982fe7cfb4d33103ee611acc310e3225ccf35852 Mon Sep 17 00:00:00 2001 From: Philip McGrath <philip@philipmcgrath.com> Date: Wed, 23 Feb 2022 11:13:43 -0500 Subject: [PATCH] example of import problems --- gnu/packages/chez-and-racket-bootstrap.scm | 4 ++++ gnu/packages/racket.scm | 3 +++ 2 files changed, 7 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index b779099fb3..ea10f7fe92 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -47,6 +47,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module ((guix licenses) #:prefix license:) #:export (chez-scheme-for-system + make-racket-vm-cgc racket-vm-for-system)) ;; Commentary: @@ -199,6 +200,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (make-racket-vm-cgc a b) + 42) + (define* (chez-scheme-for-system #:optional (system (or (%current-target-system) (%current-system)))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index c2854f84e8..08e437a722 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -58,6 +58,9 @@ (define %racket-version "8.4") ; MUST match "chez-and-racket-bootstrap.scm" (define %racket-commit (string-append "v" %racket-version)) +(define fake-racket-vm-cgc + (make-racket-vm-cgc 1 2)) + (define (extract-package-source origin spec) "Extract the source for a Racket package specified by SPEC from ORIGIN into a new file-like object. In the resulting file-like object, the package source -- 2.32.0 --8<---------------cut here---------------end--------------->8--- With this patch, trying to run `make` fails with the same kind of error we've seen before: ``` ice-9/eval.scm:293:34: error: make-racket-vm-cgc: unbound variable hint: Did you forget `(use-modules (gnu packages chez-and-racket-bootstrap))'? ``` Overall, I certainly agree that duplicating the definition of `%racket-version` is not ideal. I'd be glad for you or anyone to improve the situation, and I'll try to get my head around Maxime's email about the underlying semantics. But I am confident that v4 of this series is at least not broken, if perhaps not maximally beautiful. Especially given that I, for one, have tried things that initially seemed correct only to discover subtle problems later, I think it would be better for any refinements to come in follow-on patches later. -Philip ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-23 18:55 ` Philip McGrath @ 2022-02-23 20:31 ` Liliana Marie Prikler 2022-02-24 15:09 ` zimoun 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-23 20:31 UTC (permalink / raw) To: Philip McGrath, Philip McGrath, 53878, Ludovic Courtès Cc: Attila Lendvai, Maxime Devos, Malte Gerdes, raingloom, zimoun Hi, Am Mittwoch, dem 23.02.2022 um 13:55 -0500 schrieb Philip McGrath: > To try to be concrete, I made the patch below as a mock-up of part of > your earlier suggestion (IIUC): > > On 2/20/22 04:03, Liliana Marie Prikler wrote: > > Inside chez-and-racket-bootstrap, define (make-<package>) > functions for > > the following: > > - chez-bootstrap-bootfiles, chez-for-racket-bootstrap-bootfiles: > > Taking version and origin. > > - racket-vm-cgc: Taking version and origin. > > - racket-vm-bc: Taking racket-vm-cgc. > > - racket-vm-cs: Taking racket-vm-bc. > > > Inside racket, define %racket-version, %racket-origin, racket- > minimal > > and racket. It'd also be good if you made local definitions > > (define racket-vm-cgc (make-racket-vm-cgc %racket-version %racket- > > origin)) > > (define racket-vm-bc (make-racket-vm-bc racket-vm-cgc)) > > ... > > in this file. > > This applies on top of v4, or I've put it at > < > https://gitlab.com/philip1/guix-patches/-/commit/982fe7cfb4d33103ee611acc310e3225ccf35852 > > > if that's easier for anyone: To be fair, the issue here is with my proposal, which doesn't completely thunk through. I clarified later on that it would need another pair of brackets or – if that's easier for you – commented on the commit you've linked. > Overall, I certainly agree that duplicating the definition of > `%racket-version` is not ideal. I'd be glad for you or anyone to > improve the situation, and I'll try to get my head around Maxime's > email about the underlying semantics. > > But I am confident that v4 of this series is at least not broken, if > perhaps not maximally beautiful. Especially given that I, for one, > have tried things that initially seemed correct only to discover > subtle problems later, I think it would be better for any refinements > to come in follow-on patches later. I can understand the sentiment, but there are some things that still don't feel right for me – for instance the fact, that seemingly unrelated modules now have to pull in racket bootstrap sounds like a recipe for trouble. The final patch in the series also still does too much for me to wrap my head around, which makes it difficult to audit. Therefore, one question I have w.r.t. updating Racket is whether we could theoretically bump the version while keeping the old bootstrap, and then adjust the bootstrap by adding all the packages you've made. It does seem to be an all or nothing deal when doing the bootstrap first, but that need not necessarily hold for bootstrap second. Also, accepting for a moment that we might have to move chez-scheme and other important things into chez-scheme-and-racket-bootstrap (even though I'm not really content with it), I still wonder if we could introduce chez-scheme-for-system first (defined as simply chez-scheme initially) and adjust the callers, then move chez-scheme while keeping the function in chez.scm and finally do the magic with making it either chez or racket. I know I have a tendency towards being overly cautious when it comes to pushing big changes, so if that's the case I'd be happy if someone else were to take over. That said, I do feel somewhat lonely at the moment despite the many people specifically mentioned in "To:" and "Cc:", so I'm somewhat content with moving slowly for now. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-23 20:31 ` Liliana Marie Prikler @ 2022-02-24 15:09 ` zimoun 0 siblings, 0 replies; 214+ messages in thread From: zimoun @ 2022-02-24 15:09 UTC (permalink / raw) To: Liliana Marie Prikler Cc: Philip McGrath, Malte Gerdes, Maxime Devos, raingloom, Attila Lendvai, Ludovic Courtès, 53878, Philip McGrath Hi Liliana, Thanks Philip for these large series. > I know I have a tendency towards being overly cautious when it comes to > pushing big changes, so if that's the case I'd be happy if someone else > were to take over. That said, I do feel somewhat lonely at the moment > despite the many people specifically mentioned in "To:" and "Cc:", so > I'm somewhat content with moving slowly for now. Sorry, I am running out of time and the series is quite large; the changes are not really atomic. ;-) On Wed, 23 Feb 2022 at 21:31, Liliana Marie Prikler <liliana.prikler@gmail.com> wrote: > > But I am confident that v4 of this series is at least not broken, if > > perhaps not maximally beautiful. Especially given that I, for one, > > have tried things that initially seemed correct only to discover > > subtle problems later, I think it would be better for any refinements > > to come in follow-on patches later. > > I can understand the sentiment, but there are some things that still > don't feel right for me – for instance the fact, that seemingly > unrelated modules now have to pull in racket bootstrap sounds like a > recipe for trouble. The final patch in the series also still does too > much for me to wrap my head around, which makes it difficult to audit. I understand both sentiments. I also have some difficulties for auditing the series. Well, it needs some time to sit down, fill the coffee pot and careful review. :-) I cannot promise but I will try to give a look next week; for what my reviewing eyes are worth. Cheers, simon ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 10/15] gnu: Add racket-vm-bc. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 11/15] gnu: Add chez-scheme-for-racket Philip McGrath ` (4 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-bc): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 5eedd9a11f..ca76e78b1e 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -477,6 +477,29 @@ (define maybe-release-catalog ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) +(define-public racket-vm-bc + (package + (inherit racket-vm-cgc) + (name "racket-vm-bc") + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket BC [3M] implementation") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 11/15] gnu: Add chez-scheme-for-racket. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 10/15] gnu: Add racket-vm-bc Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 12/15] gnu: Add racket-vm-cs Philip McGrath ` (3 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez-and-racket-bootstrap.scm (unpack-nanopass+stex): (chez-scheme-for-racket): (chez-scheme-for-racket-bootstrap-bootfiles): New variables. (chez-scheme)[arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 132 +++++++++++++++++++-- 1 file changed, 121 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index ca76e78b1e..6eddc46e66 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -319,11 +319,28 @@ (define unbundle-chez-submodules "lz4" "zlib")))) +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + ;; ;; Racket VM: ;; (define %racket-version "8.4") +(define %chez-scheme-for-racket-version "9.5.7.3") +;; The version should match `(scheme-fork-version-number)`. +;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. +;; It will always be different than the upstream version! (define %racket-origin (origin (method git-fetch) @@ -551,17 +568,8 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (copy-recursively - (dirname (search-input-file (or native-inputs inputs) - "lib/chez-scheme/nanopass.ss")) - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + (lambda args + #$unpack-nanopass+stex)) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (when (directory-exists? "boot") @@ -691,6 +699,108 @@ (define-public chez-scheme-bootstrap-bootfiles work with upstream Chez Scheme so that we can bootstrap these files from source."))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version %chez-scheme-for-racket-version) + (source %racket-origin) + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license license:asl2.0))) + +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (inherit chez-scheme-bootstrap-bootfiles) + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version (package-version chez-scheme-for-racket)) + (source (package-source chez-scheme-for-racket)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) + (arguments + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 12/15] gnu: Add racket-vm-cs. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (10 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 11/15] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (2 subsequent siblings) 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cs): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 6eddc46e66..458645f037 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -517,6 +517,50 @@ (define-public racket-vm-bc This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'')."))) + +(define-public racket-vm-cs + (package + (inherit racket-vm-bc) + (name "racket-vm-cs") + (inputs + (modify-inputs (package-inputs racket-vm-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket + chez-nanopass-bootstrap + racket-vm-bc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$unpack-nanopass+stex))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. + +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 13/15] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (11 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 12/15] gnu: Add racket-vm-cs Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 15/15] gnu: racket: Update to 8.4 Philip McGrath 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 54bbee7923..be251798c3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -355,7 +355,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (12 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 2022-02-19 20:00 ` Liliana Marie Prikler 2022-02-19 6:42 ` [bug#53878] [PATCH v3 15/15] gnu: racket: Update to 8.4 Philip McGrath 14 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-for-system): New procedure. * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise * gnu/packages/chez.scm (chez-srfi): (chez-web): (chez-sockets): (chez-matchable): (chez-irregex): (chez-fmt): (chez-mit): (chez-scmutils): Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 14 +++++++++++++- gnu/packages/chez.scm | 16 ++++++++-------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 458645f037..51032fc68f 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages xorg) #:use-module ((guix licenses) #:prefix license:) - #:export (%racket-version + #:export (chez-scheme-for-system + %racket-version %racket-origin)) ;; Commentary: @@ -199,6 +200,17 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (and (nix-system->chez-machine system) + (not (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)))) + chez-scheme-for-racket + chez-scheme)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index be251798c3..d5007e0cfd 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -74,7 +74,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -105,7 +105,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -170,7 +170,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -256,7 +256,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -288,7 +288,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -319,7 +319,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -382,7 +382,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -413,7 +413,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index cb7d4425af..24f5b1e9c1 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -450,7 +450,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index 74a649b8a1..a7ab12a0c4 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-19 20:00 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-19 20:00 UTC (permalink / raw) To: Philip McGrath, 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > +(define* (chez-scheme-for-system #:optional > + (system (or (%current-target- > system) > + (%current-system)))) > + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' > supports SYSTEM, > +including support for native threads." > + (if (and (nix-system->chez-machine system) > + (not (and=> (chez-upstream-features-for-system system) > + (cut memq 'threads <>)))) > + chez-scheme-for-racket > + chez-scheme)) Given your previous explanation this series looks clean enough so far, but this looks like a bug. You probably want (if (and (nix-system->chez-machine system) (and=> (chez-upstream-features-for-system system) (cut memq 'threads <>))) chez-scheme chez-scheme-for-racket) This variant would in particular use chez-scheme-for-racket if nix- system->chez-machine returns #f. I can make that adjustment for you assuming I interpreted this correctly. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v3 15/15] gnu: racket: Update to 8.4. 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (13 preceding siblings ...) 2022-02-19 6:42 ` [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-19 6:42 ` Philip McGrath 14 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 6:42 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Ludovic Courtès, Attila Lendvai, Philip McGrath, Malte Gerdes, zimoun * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New file. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): New procedure. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 3 +- gnu/packages/chez-and-racket-bootstrap.scm | 9 + ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1554 +++++++++++------ 4 files changed, 1067 insertions(+), 525 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 3a6a4a48b3..1efe54f9a2 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1752,6 +1752,7 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 51032fc68f..9f501d0eac 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -47,6 +47,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module ((guix licenses) #:prefix license:) #:export (chez-scheme-for-system + racket-vm-for-system %racket-version %racket-origin)) @@ -211,6 +212,14 @@ (define* (chez-scheme-for-system #:optional chez-scheme-for-racket chez-scheme)) +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..67e22623b3 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,90 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) - -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Racket -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementation -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are further -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compiler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: - -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) - -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) - + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) - (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (version %racket-version) + (source %racket-origin) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs (list openssl sqlite (racket-vm-for-system))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `make-installation-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install` + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (ice-9 match)) + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key inputs configure-flags make-flags + #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each (lambda (name) + (copy-recursively + (string-append "pkgs/" name) + (string-append #$output "/lib/racket/pkgs/" name))) + '("base" "racket-lib")))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +145,77 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (list cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:phases parent-phases #~%standard-phases) + #~(modify-phases #$parent-phases + (delete 'unpack) + (replace 'build + (lambda args + (mkdir-p (string-append #$output "/lib/racket/pkgs")) + (for-each + (match-lambda + ((name src) + (copy-recursively + src + (string-append #$output "/lib/racket/pkgs/" name)))) + '(#$@main-distribution-packages)))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -539,82 +227,900 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) + +(define-public main-distribution-packages + (let ((%racket-commit (string-append "v" %racket-version))) + (append-map + (match-lambda + ((source . pkgs) + (map (match-lambda + ((? string? name) + (list name (file-append source (string-append "/" name)))) + ((name ".") + (list name source)) + ((name rel-path) + (list name (file-append source (string-append "/" rel-path))))) + pkgs))) + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,%racket-origin + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" "distributed-places-doc" "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" + (package-version (racket-vm-for-system))))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" "future-visualizer-pict" "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] Fwd: Re: [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-19 22:34 ` Philip McGrath 2022-02-19 22:35 ` [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 4 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 22:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Philip McGrath, Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 1734 bytes --] (sorry, missed "reply all" ...) ---------- Forwarded Message ---------- Subject: Re: [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez- scheme-for-system'. Date: Saturday, February 19, 2022, 5:29:05 PM EST From: Philip McGrath <philip@philipmcgrath.com> To: Liliana Marie Prikler <liliana.prikler@gmail.com> Hi, On Saturday, February 19, 2022 3:00:37 PM EST you wrote: > Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > > +(define* (chez-scheme-for-system #:optional > > + (system (or (%current-target- > > system) > > + (%current-system)))) > > + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' > > supports SYSTEM, > > +including support for native threads." > > + (if (and (nix-system->chez-machine system) > > + (not (and=> (chez-upstream-features-for-system system) > > + (cut memq 'threads <>)))) > > + chez-scheme-for-racket > > + chez-scheme)) > > Given your previous explanation this series looks clean enough so far, > but this looks like a bug. You probably want > (if (and (nix-system->chez-machine system) > (and=> (chez-upstream-features-for-system system) > (cut memq 'threads <>))) > chez-scheme > chez-scheme-for-racket) > This variant would in particular use chez-scheme-for-racket if nix- > system->chez-machine returns #f. > > I can make that adjustment for you assuming I interpreted this > correctly. Thanks for catching this! I must have gotten myself confused while changing to chez-upstream-features-for-system from the chez-machine->upstream-restriction version. -Philip ----------------------------------------- [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-19 22:34 ` [bug#53878] Fwd: Re: [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-19 22:35 ` Philip McGrath 2022-02-19 23:24 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 4 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-19 22:35 UTC (permalink / raw) To: 53878, Liliana Marie Prikler Cc: Philip McGrath, Ludovic Courtès, Attila Lendvai, Malte Gerdes, zimoun [-- Attachment #1: Type: text/plain, Size: 1926 bytes --] (... on this one, too) ---------- Forwarded Message ---------- Subject: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc. Date: Saturday, February 19, 2022, 5:27:39 PM EST From: Philip McGrath <philip@philipmcgrath.com> To: Liliana Marie Prikler <liliana.prikler@gmail.com> Hi, On Saturday, February 19, 2022 3:46:47 PM EST you wrote: > Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > > * gnu/packages/patches/racket-enable-scheme-backport.patch: New > > patch. > > * gnu/local.mk (dist_patch_DATA): Add it. > > * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez- > > submodules, > > %racket-version, %racket-origin, racket-vm-cgc): New variables. > > (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. > > Something weird happened to me just now trying to build this series. > While compiling emacs-xyz, an error was raised regarding %racket- > version not existing and and import being missing. Assuming that you > didn't mess up an include somewhere, there could be a cycle meaning > we'd have to pass the version and origin by function as I originally > said in my reply to v2. > > I'll clean up my work tree and try to reapply it, but that will take > some time. Since you mentioned re-exports causing issues, I'd like to > ask if you've made a similar experience, but the results got somehow > hidden after the right incantations. I haven't seen errors from emacs-xyz, but I have gotten errors about %racket- version not existing: at the time I thought it was just a problem with incremental rebuilds while moving back and forward through history, but, having just refreshed my memory on more details of the cyclic issues, I think it may be related. I'll send another email presently with details once I've gathered references. For now, I found that `rm gnu/packages/*.go` was enough to get `make` to succeed again. -Philip ----------------------------------------- [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc. 2022-02-19 22:35 ` [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-19 23:24 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-19 23:24 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Philip McGrath, Attila Lendvai, Malte Gerdes, raingloom, zimoun [-- Attachment #1: Type: text/plain, Size: 6120 bytes --] Hi, On Saturday, February 19, 2022 5:35:22 PM EST Philip McGrath wrote: > On Saturday, February 19, 2022 3:46:47 PM EST you wrote: > > Am Samstag, dem 19.02.2022 um 01:42 -0500 schrieb Philip McGrath: > > > * gnu/packages/patches/racket-enable-scheme-backport.patch: New > > > patch. > > > * gnu/local.mk (dist_patch_DATA): Add it. > > > * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez- > > > submodules, > > > %racket-version, %racket-origin, racket-vm-cgc): New variables. > > > (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. > > > > Something weird happened to me just now trying to build this series. > > While compiling emacs-xyz, an error was raised regarding %racket- > > version not existing and and import being missing. Assuming that you > > didn't mess up an include somewhere, there could be a cycle meaning > > we'd have to pass the version and origin by function as I originally > > said in my reply to v2. > > > > I'll clean up my work tree and try to reapply it, but that will take > > some time. Since you mentioned re-exports causing issues, I'd like to > > ask if you've made a similar experience, but the results got somehow > > hidden after the right incantations. > > I haven't seen errors from emacs-xyz, but I have gotten errors about > %racket- version not existing: at the time I thought it was just a problem > with incremental rebuilds while moving back and forward through history, > but, having just refreshed my memory on more details of the cyclic issues, > I think it may be related. I'll send another email presently with details > once I've gathered references. > > For now, I found that `rm gnu/packages/*.go` was enough to get `make` to > succeed again. This reminded me of one of the commits I mentioned yesterday in <https:// issues.guix.gnu.org/53878#66>: > commit 96db2ff145ecbd962206eae815b065bda7ed3d9f > Author: Ludovic Courtès <ludo@gnu.org> > Date: Tue Sep 7 15:11:46 2021 +0200 > > gnu: racket-minimal: Remove top-level reference to 'chez-scheme'. > > This could cause build errors; for instance, doing: > make && touch gnu/packages/chez.scm && make > > would trigger a "chez-scheme: unbound variable" error. > > * gnu/packages/racket.scm (racket-minimal)[source]: Add 'modules' > field. In 'snippet', remove top-level reference to CHEZ-SCHEME, which > could cause build errors. Simplify snippet. That symptom of an unbound variable error on re-making sounds like what's going on. In <https://issues.guix.gnu.org/48682#7>, Ludo’ explained: On Monday, May 31, 2021 12:23:27 PM EST Ludovic Courtès wrote: > Philip McGrath <philip@philipmcgrath.com> skribis: > > On 5/29/21 4:15 PM, Ludovic Courtès wrote: > >> In general we cannot use #:select for (gnu packages …) modules because > >> that doesn’t play well with circular module dependencies. > > > > Ah, interesting, I'll keep that in mind. I'm used to Racket, where all > > cyclic module dependencies cause errors at compile time. > > Yeah, in hindsight, that’s probably safer… > > > Do you have any advice on what would be good practice? > > For package modules, the main things are: > > 1. Don’t use #:select or #:autoload for (gnu packages …) modules in a > (gnu packages …) module. > > 2. At the top level of a module, only refer to variables within that > module. For instance, the following would be wrong: > > (define-module (gnu packages racket) > #:use-module (gnu packages chez) > …) > > (define whatever > ;; Wrong because ‘chez-scheme’ is defined in another module, > ;; which might be part of a cycle with this one. > (package (inherit chez-scheme) …)) > > (define something > (package > ;; … > (license (package-license chez-scheme)))) ;likewise > > Note that references from ‘inputs’ and ‘arguments’ fields are perfectly > fine (fortunately!) because those fields are “thunked” (their value is > wrapped in a thunk). > My understanding of the semantics of Guile modules is strictly less than the content of that thread. I'm most familiar with Racket modules, and I have some understanding of how those semantics differ from R6RS library semantics. I think I had seized in my memory of № 2 on "at the top level of a module", and I'd filled in my usual (Racket) understanding of "at the top level of a module" as a less formal way of saying "in a module context", in the sense of "expansion contexts".[1] But Ludo’'s examples show that's wrong: those uses of `chez scheme` are in what the "expansion contexts" model would call "expression contexts". Instead, I think rule № 2 prohibits any reference to a variable imported from another (gnu packages ...) module that will be evaluated when the (gnu packages ...) modules are—visited? instantiated? [2][3]—IDK when exactly, but, for practical purposes, any variable reference that is not underneath a lambda abstraction. If that's right, IIUC, it would mean that: (define chez-scheme-for-racket (make-chez-scheme-for-racket ...)) would also be prohibited. On the other hand, uses of `(racket-vm-for-system)` and `(chez-scheme-for- system)` in an `imports` field should still be fine, thanks to the implicit thunks. I think I can can make that work relatively well. The one thing I don't know how to avoid is defining `%racket-version` in both "chez-and-racket- bootstrap.scm" and "racket.scm", but I'll leave a cautionary comment. I'll try to make a v4 with the approach I have in mind. I'd be glad to hear better ideas, though! Especially if anyone knows more about what Guile's module semantics really are. -Philip [1]: https://docs.racket-lang.org/reference/syntax-model.html#%28part._expand-context-model%29 [2]: http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-10.html#node_sec_7.2 [4]: https://docs.racket-lang.org/reference/syntax-model.html#%28part._mod-parse%29 [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-19 22:35 ` [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-20 6:05 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath ` (17 more replies) 4 siblings, 18 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:05 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath Hi, Here is v4. I believe it avoids the import cycle. The first change from v3 is in patch 09/15, in which I changed "gnu/packages/chez-and-racket-bootstrap.scm" no longer export `%racket-version` or `%racket-origin`. The package `source` field is not thunked, so exporting the latter seems like a particular trap for the unwary. In 14/15, I looked again at the issue with `chez-scheme-for-system` that Liliana reported in <https://issues.guix.gnu.org/53878#89>, and I realized my intention had actually been to return `chez-scheme` if the specified system is completely unsupported (not that it makes much difference ...). I tweaked it slightly and added comments, since I've gotten confused about it more than once now. The changes to avoid the import cycle are primarily in 15/15. As I outlined in <https://issues.guix.gnu.org/53878#93>, I duplicated the definition of `%racket-version` in "gnu/packages/racket.scm" and added comments there and to "gnu/packages/chez-and-racket-bootstrap.scm" warning to keep them in sync. I also had to avoid the use of `%racket-origin` (or `(package-source (racket-vm-for-system))`) outside of lambda abstractions, which in particular meant that it could no longer be used in the `source` field of `racket-minimal`. Instead, I changed `racket-minimal` to handle "base" and "racket-lib" in the same way `racket` does for its component Racket packages. Recalling Liliana's comment in <https://issues.guix.gnu.org/53878#65>, since I was lifting the function to handle Racket package origins anyway to reuse it, I changed it to produce `computed-file`s that take care of extracting the right files from the origin, so `racket-minimal` can now use `union-build` and `racket` no longer needs to replace the build phase. I can immagine a `racket-build-system` helping to improve the situation, since it would presumably add `(racket-vm-for-system)` as an implicit input. It might also be useful to provide special support for packages from the main Racket Git repository: almost always, if you change transform the origin for the Racket VM, you want all of the packages developed in the same repository to use come from the transformed origin, too. But for now, v4 should avoid the import cycle problem without doing anything too ugly. -Philip Philip McGrath (15): gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: Add racket-vm-cgc. gnu: Add racket-vm-bc. gnu: Add chez-scheme-for-racket. gnu: Add racket-vm-cs. gnu: chez-mit: Support chez-scheme-for-racket. gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. gnu: racket: Update to 8.4. gnu/local.mk | 5 +- gnu/packages/chez-and-racket-bootstrap.scm | 1077 +++++++++++ gnu/packages/chez.scm | 628 +++---- gnu/packages/emacs-xyz.scm | 4 +- gnu/packages/loko.scm | 4 +- .../racket-enable-scheme-backport.patch | 465 +++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1599 +++++++++++------ 8 files changed, 2871 insertions(+), 937 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap). 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-20 6:05 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (16 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:05 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez.scm (nanopass, stex, chez-scheme): Move to ... * gnu/packages/chez-and-racket-bootstrap.scm: ... this new file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/emacs-xyz.scm: Adjust imports accordingly. * gnu/packages/loko.scm: Likewise. * gnu/packages/racket.scm: Likewise. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 278 +++++++++++++++++++++ gnu/packages/chez.scm | 225 +---------------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- gnu/packages/racket.scm | 2 +- 6 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 gnu/packages/chez-and-racket-bootstrap.scm diff --git a/gnu/local.mk b/gnu/local.mk index 75a60b0093..e802b4450b 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -144,6 +144,7 @@ GNU_SYSTEM_MODULES = \ %D%/packages/certs.scm \ %D%/packages/check.scm \ %D%/packages/chemistry.scm \ + %D%/packages/chez-and-racket-bootstrap.scm \ %D%/packages/chez.scm \ %D%/packages/chicken.scm \ %D%/packages/chromium.scm \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm new file mode 100644 index 0000000000..f102b099fb --- /dev/null +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -0,0 +1,278 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Federico Beffa <beffa@fbengineering.ch> +;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> +;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> +;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix 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 General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu packages chez-and-racket-bootstrap) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix git-download) + #:use-module (guix utils) + #:use-module (guix gexp) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages compression) + #:use-module (gnu packages ghostscript) + #:use-module (gnu packages linux) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages netpbm) + #:use-module (gnu packages tex) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +;; Commentary: +;; +;; Alphabetically and chronologically, Chez comes before Racket. +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Putting the relevant definitions together in this module avoids having to +;; work around dependency cycles. +;; +;; Code: + +(define nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +(define stex + ;; This commit includes a fix, which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (version "1.2.2") + (version (git-version version "1" commit))) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name "stex" version))))) + +(define-public chez-scheme + (package + (name "chez-scheme") + (version "9.5.6") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet + ;; Remove bundled libraries. + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))))))) + (build-system gnu-build-system) + (inputs + `(("libuuid" ,util-linux "lib") + ("zlib" ,zlib) + ("zlib:static" ,zlib "static") + ("lz4" ,lz4) + ("lz4:static" ,lz4 "static") + ;; for expeditor: + ("ncurses" ,ncurses) + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + ("libx11" ,libx11))) + (native-inputs + `(("nanopass" ,nanopass) ; source only + ;; for docs + ("stex" ,stex) + ("xorg-rgb" ,xorg-rgb) + ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek))) + ("ghostscript" ,ghostscript) + ("netpbm" ,netpbm))) + (native-search-paths + (list (search-path-specification + (variable "CHEZSCHEMELIBDIRS") + (files (list (string-append "lib/csv" version "-site")))))) + (outputs '("out" "doc")) + (arguments + `(#:modules + ((guix build gnu-build-system) + (guix build utils) + (ice-9 ftw) + (ice-9 match)) + #:test-target "test" + #:configure-flags + '("--threads") ;; TODO when we fix armhf, it doesn't support --threads + #:phases + (modify-phases %standard-phases + ;; put these where configure expects them to be + (add-after 'unpack 'unpack-nanopass+stex + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (for-each (lambda (dep) + (define src + (assoc-ref (or native-inputs inputs) dep)) + (copy-recursively src dep + #:keep-mtime? #t)) + '("nanopass" "stex")))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs outputs + (configure-flags '()) + #:allow-other-keys) + (let* ((zlib-static (assoc-ref inputs "zlib:static")) + (lz4-static (assoc-ref inputs "lz4:static")) + (out (assoc-ref outputs "out")) + ;; add flags which are always required: + (flags (cons* + (string-append "--installprefix=" out) + (string-append "ZLIB=" zlib-static "/lib/libz.a") + (string-append "LZ4=" lz4-static "/lib/liblz4.a") + ;; Guix will do compress man pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" ,(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke + "./configure" + flags)))) + ;; The binary file name is called "scheme" as is the one from MIT/GNU + ;; Scheme. We add a symlink to use in case both are installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (bin (string-append out "/bin")) + (lib (string-append out "/lib")) + (name "chez-scheme")) + (symlink (string-append bin "/scheme") + (string-append bin "/" name)) + (map (lambda (file) + (symlink file (string-append (dirname file) + "/" name ".boot"))) + (find-files lib "scheme.boot"))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (stex-output "/tmp") + (doc-dir (string-append stex-output + "/share/doc/" + stex+version))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/" + stex+version) + (string-append "Scheme=" + (assoc-ref outputs "out") + "/bin/scheme")) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (let* ((chez+version (strip-store-file-name + (assoc-ref outputs "out"))) + (stex+version + (strip-store-file-name + (assoc-ref (or native-inputs inputs) "stex"))) + (scheme (string-append (assoc-ref outputs "out") + "/bin/scheme")) + ;; see note on stex-output in phase build-stex, above: + (stexlib (string-append "/tmp" + "/lib/" + stex+version)) + (doc-dir (string-append (assoc-ref outputs "doc") + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" + "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))) + ;; Chez Scheme does not have a MIPS backend. + ;; FIXME: Debian backports patches to get armhf working. + ;; We should too. It is the Chez machine type arm32le + ;; (no threaded version upstream yet, though there is in + ;; Racket's fork), more specifically (per the release notes) ARMv6. + (supported-systems (fold delete %supported-systems + '("mips64el-linux" "armhf-linux"))) + (home-page "https://cisco.github.io/ChezScheme/") + (synopsis "R6RS Scheme compiler and run-time") + (description + "Chez Scheme is a compiler and run-time system for the language of the +Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler +generates native code for each target processor, with support for x86, x86_64, +and 32-bit PowerPC architectures.") + (license license:asl2.0))) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..caf61a95f5 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -4,7 +4,6 @@ ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2019 Brett Gilio <brettg@gnu.org> ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,234 +31,12 @@ (define-module (gnu packages chez) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (guix build-system gnu) - #:use-module (gnu packages compression) - #:use-module (gnu packages ncurses) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages ghostscript) - #:use-module (gnu packages linux) - #:use-module (gnu packages netpbm) #:use-module (gnu packages tex) - #:use-module (gnu packages compression) - #:use-module (gnu packages image) - #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) -(define nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - -(define-public chez-scheme - (package - (name "chez-scheme") - (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) - (build-system gnu-build-system) - (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) - (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) - (native-search-paths - (list (search-path-specification - (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) - (outputs '("out" "doc")) - (arguments - `(#:modules - ((guix build gnu-build-system) - (guix build utils) - (ice-9 ftw) - (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) - ;; Chez Scheme does not have a MIPS backend. - ;; FIXME: Debian backports patches to get armhf working. - ;; We should too. It is the Chez machine type arm32le - ;; (no threaded version upstream yet, though there is in - ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) - (home-page "https://cisco.github.io/ChezScheme/") - (synopsis "R6RS Scheme compiler and run-time") - (description - "Chez Scheme is a compiler and run-time system for the language of the -Revised^6 Report on Scheme (R6RS), with numerous extensions. The compiler -generates native code for each target processor, with support for x86, x86_64, -and 32-bit PowerPC architectures.") - (license asl2.0))) - (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 49748abd32..6430318ec5 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -145,7 +145,7 @@ (define-module (gnu packages emacs-xyz) #:use-module (gnu packages aspell) #:use-module (gnu packages audio) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages cmake) #:use-module (gnu packages code) #:use-module (gnu packages cpp) diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..74a649b8a1 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -24,7 +24,7 @@ (define-module (gnu packages loko) #:use-module (gnu packages package-management) #:use-module (gnu packages guile) #:use-module (gnu packages guile-xyz) - #:use-module (gnu packages chez)) + #:use-module (gnu packages chez-and-racket-bootstrap)) (define-public loko-scheme (package diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..865fdff70f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -34,7 +34,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) - #:use-module (gnu packages chez) + #:use-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages compression) #:use-module (gnu packages databases) #:use-module (gnu packages fontutils) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath @ 2022-02-20 6:05 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (15 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:05 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". * gnu/packages/chez.scm (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez-and-racket-bootstrap.scm | 2 +- gnu/packages/chez.scm | 373 +++++++++++---------- 2 files changed, 191 insertions(+), 184 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f102b099fb..1ed4631ced 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -136,7 +136,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index caf61a95f5..54bbee7923 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -37,6 +37,28 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1)) + +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -54,13 +76,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -85,42 +105,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -144,95 +170,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -253,10 +258,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -284,10 +290,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -314,17 +321,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -354,10 +362,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -386,46 +395,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) (with-directory-excursion (dirname mk-file) (apply invoke "make" "build" make-flags))))) (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 03/15] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-20 6:05 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath ` (14 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:05 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez-and-racket-bootstrap (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1ed4631ced..11d570059b 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -114,9 +114,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -169,14 +167,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-20 6:05 ` [bug#53878] [PATCH v4 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-20 6:05 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 05/15] gnu: chez-scheme: Use new package style Philip McGrath ` (13 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:05 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New private functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. --- gnu/packages/chez-and-racket-bootstrap.scm | 118 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 11d570059b..1a923fe62d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -28,7 +28,9 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix utils) #:use-module (guix gexp) #:use-module (ice-9 match) + #:use-module (ice-9 regex) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -61,6 +63,115 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; + (define nanopass (let ((version "1.9.2")) (origin @@ -264,8 +375,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 05/15] gnu: chez-scheme: Use new package style. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-20 6:05 ` [bug#53878] [PATCH v4 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 06/15] gnu: Add stex Philip McGrath ` (12 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass, stex): Make public as a temporary workaround for Racket. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 288 ++++++++++----------- gnu/packages/racket.scm | 5 +- 2 files changed, 137 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 1a923fe62d..81ac8f0774 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -172,7 +172,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -182,7 +182,7 @@ (define nanopass (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) (file-name (git-file-name "nanopass" version))))) -(define stex +(define-public stex ;; This commit includes a fix, which we would otherwise want to use as ;; patch. Let's revert to tagged releases as soon as one becomes available. (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") @@ -199,86 +199,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -286,90 +280,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 865fdff70f..a1ba57cca3 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,9 +333,8 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) + ("stex" ,stex) + ("nanopass" ,nanopass))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 06/15] gnu: Add stex. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 05/15] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 07/15] gnu: Add chez-nanopass Philip McGrath ` (11 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap'. (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Update accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 215 +++++++++++++++------ gnu/packages/racket.scm | 2 +- 2 files changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 81ac8f0774..83bf15b5fb 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -31,6 +31,7 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) #:use-module (gnu packages compression) @@ -172,30 +173,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define-public stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -232,15 +209,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -263,9 +232,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -301,32 +272,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -334,7 +282,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -370,3 +320,146 @@ (define* (stex-make #:optional (suffix "")) generates native code for each target processor, with support for x86, x86_64, and 32-bit PowerPC architectures.") (license license:asl2.0))) + +;; +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license license:expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a1ba57cca3..d8338bcd6f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -333,7 +333,7 @@ (define-public racket-bootstrap-chez-bootfiles `(("racket" ,(if (%current-target-system) racket-minimal racket-minimal-bc-3m)) - ("stex" ,stex) + ("stex" ,(package-source stex)) ("nanopass" ,nanopass))) (arguments `(#:phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 07/15] gnu: Add chez-nanopass. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 06/15] gnu: Add stex Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (10 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex'. (chez-nanopass): New variable. * gnu/packages/racket.scm (racket-bootstrap-chez-bootfiles)[native-inputs]: Adapt accordingly. --- gnu/packages/chez-and-racket-bootstrap.scm | 96 ++++++++++++++++++---- gnu/packages/racket.scm | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 83bf15b5fb..d66955d50d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -207,9 +207,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -228,10 +226,12 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (copy-recursively + (dirname (search-input-file (or native-inputs inputs) + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) (mkdir-p "stex") (with-output-to-file "stex/Mf-stex" (lambda () @@ -454,12 +454,76 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license license:expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d8338bcd6f..e8d016c07b 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -334,7 +334,7 @@ (define-public racket-bootstrap-chez-bootfiles racket-minimal racket-minimal-bc-3m)) ("stex" ,(package-source stex)) - ("nanopass" ,nanopass))) + ("nanopass" ,(package-source chez-nanopass)))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 07/15] gnu: Add chez-nanopass Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 09/15] gnu: Add racket-vm-cgc Philip McGrath ` (9 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath This might seem a bit silly in isolation, but it makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. --- gnu/packages/chez-and-racket-bootstrap.scm | 51 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index d66955d50d..366815634d 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -187,7 +187,7 @@ (define-public chez-scheme (sha256 (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) + (file-name (git-file-name "chez-scheme" version)) (snippet #~(begin (use-modules (guix build utils)) (for-each (lambda (dir) @@ -207,7 +207,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -237,6 +239,14 @@ (define-public chez-scheme (lambda () ;; otherwise, it will try to download submodules (display "# to placate ../configure"))))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -321,6 +331,43 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license license:asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 09/15] gnu: Add racket-vm-cgc. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 10/15] gnu: Add racket-vm-bc Philip McGrath ` (8 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/patches/racket-enable-scheme-backport.patch: New patch. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (unbundle-chez-submodules, %racket-version, %racket-origin, racket-vm-cgc): New variables. (chez-scheme)[source]<snippet>: Use 'unbundle-chez-submodules'. --- gnu/local.mk | 1 + gnu/packages/chez-and-racket-bootstrap.scm | 316 +++++++++++- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ 3 files changed, 773 insertions(+), 9 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index e802b4450b..5fcbe3a391 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1750,6 +1750,7 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 366815634d..c99b8ff19e 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -34,8 +34,11 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages) + #:use-module (gnu packages autotools) + #:use-module (gnu packages bash) #:use-module (gnu packages compression) #:use-module (gnu packages ghostscript) + #:use-module (gnu packages libffi) #:use-module (gnu packages linux) #:use-module (gnu packages ncurses) #:use-module (gnu packages netpbm) @@ -62,6 +65,136 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; Putting the relevant definitions together in this module avoids having to ;; work around dependency cycles. ;; +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: +;; +;; - Racket BC [CGC] can be built with only a C compiler (except for +;; one caveat discussed below). +;; - Racket BC [3M] needs an existing Racket to run "xform", +;; which transforms its own C source code to add additional annotations +;; for the precise garbage collector. +;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. +;; It also needs an existing Racket to compile Racket-implemented +;; parts of the runtime system to R6RS libraries. +;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate +;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler +;; purely from source into Racket and apply the compiler to itself, +;; producing the needed bootfiles (albeit very slowly). +;; Any variant of Racket since version 7.1 can run the simulation. +;; +;; So, we build CGC to build 3M to build bootfiles and CS. +;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; +;; One remaining bootstrapping limitation is that Racket's reader, module +;; system, and macro expander are implemented in Racket. For Racket CS, +;; they are compiled to R6RS libraries as discussed above. This note from the +;; README file applies to all such subsystems: +;; +;; The Racket version must be practically the same as the current Racket +;; verson, although it can be the Racket BC implementation (instead of +;; the Racket CS implementation). +;; +;; Unlike Chez Scheme boot files, the files generated in "schemified" +;; are human-readable and -editable Scheme code. That provides a way +;; out of bootstrapping black holes, even without BC. +;; +;; However, other Racket subsystems implemented in Racket for Racket CS +;; use older C implementations for Racket BC, whereas the reader, expander, +;; and module system were completely replaced with the Racket implementation +;; +;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) +;; are embeded in C as a static string constant. Eventually, they are further +;; compiled by the C-implemented Racket BC bytecode and JIT compilers. +;; (On platforms where Racket BC's JIT is not supported, yet another compiler +;; instead compiles the linklets to C code, but this is not a bootstrapping +;; issue.) +;; ;; Code: (define (chez-machine->nonthreaded machine) @@ -169,6 +302,179 @@ (define* (chez-upstream-features-for-system #:optional (else '(threads)))) +;; +;; Chez auxiliary G-expressions: +;; + +(define unbundle-chez-submodules + #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))) + +;; +;; Racket VM: +;; + +(define %racket-version "8.4") +(define %racket-origin + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit (string-append "v" %racket-version)))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" %racket-version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + #$unbundle-chez-submodules) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + +(define (racket-vm-common-configure-flags) + ;; under a lambda extraction to avoid evaluating bash-minimal too early + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip" + "--enable-origtree")) + +(define-public racket-vm-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-vm-cgc") + (version %racket-version) + (source %racket-origin) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants + (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") + #:phases + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + ;; ;; Chez Scheme: ;; @@ -188,15 +494,7 @@ (define-public chez-scheme (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) (file-name (git-file-name "chez-scheme" version)) - (snippet #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib")))))) + (snippet unbundle-chez-submodules))) (build-system gnu-build-system) (inputs (list diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 10/15] gnu: Add racket-vm-bc. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 09/15] gnu: Add racket-vm-cgc Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 11/15] gnu: Add chez-scheme-for-racket Philip McGrath ` (7 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-bc): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index c99b8ff19e..2f649fe67f 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -475,6 +475,29 @@ (define maybe-release-catalog ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) +(define-public racket-vm-bc + (package + (inherit racket-vm-cgc) + (name "racket-vm-bc") + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket BC [3M] implementation") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 11/15] gnu: Add chez-scheme-for-racket. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 10/15] gnu: Add racket-vm-bc Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 12/15] gnu: Add racket-vm-cs Philip McGrath ` (6 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez-and-racket-bootstrap.scm (unpack-nanopass+stex): (chez-scheme-for-racket): (chez-scheme-for-racket-bootstrap-bootfiles): New variables. (chez-scheme)[arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 132 +++++++++++++++++++-- 1 file changed, 121 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 2f649fe67f..25f1ff52f8 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -317,11 +317,28 @@ (define unbundle-chez-submodules "lz4" "zlib")))) +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + ;; ;; Racket VM: ;; (define %racket-version "8.4") +(define %chez-scheme-for-racket-version "9.5.7.3") +;; The version should match `(scheme-fork-version-number)`. +;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. +;; It will always be different than the upstream version! (define %racket-origin (origin (method git-fetch) @@ -549,17 +566,8 @@ (define-public chez-scheme #:phases #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (copy-recursively - (dirname (search-input-file (or native-inputs inputs) - "lib/chez-scheme/nanopass.ss")) - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + (lambda args + #$unpack-nanopass+stex)) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (when (directory-exists? "boot") @@ -689,6 +697,108 @@ (define-public chez-scheme-bootstrap-bootfiles work with upstream Chez Scheme so that we can bootstrap these files from source."))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version %chez-scheme-for-racket-version) + (source %racket-origin) + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license license:asl2.0))) + +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (inherit chez-scheme-bootstrap-bootfiles) + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version (package-version chez-scheme-for-racket)) + (source (package-source chez-scheme-for-racket)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) + (arguments + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme."))) + ;; ;; Chez's bootstrap dependencies: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 12/15] gnu: Add racket-vm-cs. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (10 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 11/15] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (5 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-cs): New variable. --- gnu/packages/chez-and-racket-bootstrap.scm | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index 25f1ff52f8..f8fc4c7ea1 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -515,6 +515,50 @@ (define-public racket-vm-bc This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'')."))) + +(define-public racket-vm-cs + (package + (inherit racket-vm-bc) + (name "racket-vm-cs") + (inputs + (modify-inputs (package-inputs racket-vm-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-vm-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket + chez-nanopass-bootstrap + racket-vm-bc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$unpack-nanopass+stex))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. + +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + ;; ;; Chez Scheme: ;; -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 13/15] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (11 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 12/15] gnu: Add racket-vm-cs Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath ` (4 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 54bbee7923..be251798c3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -355,7 +355,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system'. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (12 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4 Philip McGrath ` (3 subsequent siblings) 17 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/chez-and-racket-bootstrap.scm (chez-scheme-for-system): New procedure. * gnu/packages/loko.scm (loko-scheme): Use 'chez-scheme-for-system'. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise * gnu/packages/chez.scm (chez-srfi): (chez-web): (chez-sockets): (chez-matchable): (chez-irregex): (chez-fmt): (chez-mit): (chez-scmutils): Likewise. --- gnu/packages/chez-and-racket-bootstrap.scm | 17 ++++++++++++++++- gnu/packages/chez.scm | 16 ++++++++-------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index f8fc4c7ea1..e837d49c63 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -45,7 +45,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages tex) #:use-module (gnu packages xorg) #:use-module ((guix licenses) - #:prefix license:)) + #:prefix license:) + #:export (chez-scheme-for-system)) ;; Commentary: ;; @@ -197,6 +198,20 @@ (define-module (gnu packages chez-and-racket-bootstrap) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (or + ;; full support upstream + (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)) + ;; no support anywhere + (not (nix-system->chez-machine system))) + chez-scheme + chez-scheme-for-racket)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index be251798c3..d5007e0cfd 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -74,7 +74,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -105,7 +105,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -170,7 +170,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -256,7 +256,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -288,7 +288,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -319,7 +319,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -382,7 +382,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -413,7 +413,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index 6430318ec5..ccd05130ca 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index 74a649b8a1..a7ab12a0c4 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (13 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-20 6:06 ` Philip McGrath 2022-02-20 10:16 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 subsequent siblings) 17 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-20 6:06 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, Malte Gerdes, raingloom, zimoun, Philip McGrath * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New file. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): New procedure. * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. Rewrite to use 'racket-vm-for-system', label-less inputs, G-expressions, and Git origins for main-distribution packages. --- gnu/local.mk | 3 +- gnu/packages/chez-and-racket-bootstrap.scm | 15 +- ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1596 +++++++++++------ 4 files changed, 1118 insertions(+), 522 deletions(-) create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 5fcbe3a391..2fb4440eee 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1751,6 +1751,7 @@ dist_patch_DATA = \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/chez-and-racket-bootstrap.scm b/gnu/packages/chez-and-racket-bootstrap.scm index e837d49c63..b779099fb3 100644 --- a/gnu/packages/chez-and-racket-bootstrap.scm +++ b/gnu/packages/chez-and-racket-bootstrap.scm @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket-bootstrap) #:use-module (gnu packages xorg) #:use-module ((guix licenses) #:prefix license:) - #:export (chez-scheme-for-system)) + #:export (chez-scheme-for-system + racket-vm-for-system)) ;; Commentary: ;; @@ -212,6 +213,14 @@ (define* (chez-scheme-for-system #:optional chez-scheme chez-scheme-for-racket)) +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -349,7 +358,9 @@ (define unpack-nanopass+stex ;; Racket VM: ;; -(define %racket-version "8.4") +(define %racket-version "8.4") ; MUST match "racket.scm" +;; The definition of %racket-version is duplicated to avoid an import cycle: +;; see <https://issues.guix.gnu.org/53878#93>. (define %chez-scheme-for-racket-version "9.5.7.3") ;; The version should match `(scheme-fork-version-number)`. ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..1e018eaa79 --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index e8d016c07b..c2854f84e8 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -30,7 +28,10 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -47,200 +48,161 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) + #:prefix license:)) + +(define %racket-version "8.4") ; MUST match "chez-and-racket-bootstrap.scm" +;; The definition of %racket-version is duplicated to avoid an import cycle: +;; see <https://issues.guix.gnu.org/53878#93>. +(define %racket-commit + (string-append "v" %racket-version)) + +(define (extract-package-source origin spec) + "Extract the source for a Racket package specified by SPEC from ORIGIN into +a new file-like object. In the resulting file-like object, the package source +will be in the directory \"/share/racket/pkgs/NAME/\", where NAME is the Racket +name for the package. + +SPEC is a list of the form: + + (NAME PATH) + +where PATH is the path to the package source relative to ORIGIN---possibly +`\".\"`. As a special case, SPEC may also be given a string, which is +equivalent to: + + (NAME NAME) + +Examples: -;; Commentary: -;; -;; Here's how bootstrapping minimal Racket works: -;; -;; - Racket BC [CGC] can be built with only a C compiler (except for -;; one caveat discussed below). -;; - Racket BC [3M] needs an existing Racket to run "xform", -;; which transforms its own C source code to add additional annotations -;; for the precise garbage collector. -;; - Racket CS needs (bootfiles for) Racket's fork of Chez Scheme. -;; It also needs an existing Racket to compile Racket-implemented -;; parts of the runtime system to R6RS libraries. -;; - Chez Scheme also needs bootfiles for itself, but Racket can simulate -;; enough of Chez Scheme to load Racket's fork of the Chez Scheme compiler -;; purely from source into Racket and apply the compiler to itself, -;; producing the needed bootfiles (albeit very slowly). -;; Any variant of Racket since version 7.1 can run the simulation. -;; -;; So, we build CGC to build 3M to build bootfiles and CS. -;; -;; One remaining bootstrapping limitation is that Racket's reader, module -;; system, and macro expander are implemented in Racket. For Racket CS, -;; they are compiled to R6RS libraries as discussed above. This note from the -;; README file applies to all such subsystems: -;; -;; The Racket version must be practically the same as the current Racket -;; verson, although it can be the Racket BC implementation (instead of -;; the Racket CS implementation). -;; -;; Unlike Chez Scheme boot files, the files generated in "schemified" -;; are human-readable and -editable Scheme code. That provides a way -;; out of bootstrapping black holes, even without BC. -;; -;; However, other Racket subsystems implemented in Racket for Racket CS -;; use older C implementations for Racket BC, whereas the reader, expander, -;; and module system were completely replaced with the Racket implementation -;; as of Racket 7.0. -;; -;; For Racket BC, the compiled "linklet" s-expressions (primitive modules) -;; are embeded in C as a static string constant. Eventually, they are further -;; compiled by the C-implemented Racket BC bytecode and JIT compilers. -;; (On platforms where Racket BC's JIT is not supported, yet another compiler -;; instead compiles the linklets to C code, but this is not a bootstrapping -;; issue.) -;; -;; Code: +- \"expeditor\" +- (\"main-distribution\" \".\") +- (\"racket-lib\" \"pkgs/racket-lib\")" + (match (match spec + ((? string? name) + (list name (file-append origin (string-append "/" name)))) + ((name ".") + (list name origin)) + ((name path) + (list name (file-append origin (string-append "/" path))))) + ((name src) + (computed-file + (string-append "racket-pkg-" name) + (with-imported-modules `((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p (string-append #$output "/share/racket/pkgs")) + (copy-recursively #$src (string-append #$output + "/share/racket/pkgs/" + #$name)))))))) + +(define (extract-package-source* source-groups) + "Return a list of file-like objects containing the sources of the Racket +packages specified by SOURCE-GROUPS, a list of the form: -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) + ((ORIGIN SPEC ...) ...) -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) +The result is equivalent to: + (append (list (extract-package-source ORIGIN SPEC) ...) ...)" + (append-map (match-lambda + ((origin . specs) + (map (cut extract-package-source origin <>) + specs))) + source-groups)) (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) + (version %racket-version) + (source #f) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) - ;; only for CS - ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) - (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (cons* openssl + sqlite + (racket-vm-for-system) + (extract-package-source* + `((,(package-source (racket-vm-for-system)) + ("base" "pkgs/base") + ("racket-lib" "pkgs/racket-lib")))))) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) - (guix build gnu-build-system) - (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `make-installation-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install` + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format + #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -254,280 +216,832 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) - - -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) - (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) - - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,(package-source stex)) - ("nanopass" ,(package-source chez-nanopass)))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0))))) - - -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) - + (license (list license:asl2.0 license:expat)))) (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - #t)))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + (cons* + cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (racket-vm-for-system) + (extract-package-source* + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,(package-source (racket-vm-for-system)) + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name + (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name + (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" + "distributed-places-doc" + "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" %racket-version))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" + "future-visualizer-pict" + "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name + (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -539,82 +1053,126 @@ (define dest (string-append pkgs-dir "/" pkg)) DrRacket IDE, libraries for GUI and web programming, and implementations of languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) - (command-line - #:args (parent-layer prefix . lib-dir*) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] - [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config + (define tethered? #f) + (define parent #f) + (define extra-foreign-lib-search-dirs '()) + (define-values [vm-dir prefix] + (command-line + #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (vm-dir prefix) + (values vm-dir prefix))) + (let* ([config + (for/fold + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config 'lib-search-dirs - (append rkt - lib-dir* - extra)))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [config + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4. 2022-02-20 6:06 ` [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-20 10:16 ` Liliana Marie Prikler 2022-02-20 14:09 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-20 10:16 UTC (permalink / raw) To: Philip McGrath, 53878, Liliana Marie Prikler, Ludovic Courtès Cc: Attila Lendvai, zimoun, Malte Gerdes, raingloom Hi, Am Sonntag, dem 20.02.2022 um 01:06 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: > New > file. > * gnu/local.mk (dist_patch_DATA): Add it. > * gnu/packages/chez-and-racket-bootstrap.scm (racket-vm-for-system): > New > procedure. > * gnu/packages/racket.scm (racket-minimal, racket): Update to 8.4. > Rewrite to use 'racket-vm-for-system', label-less inputs, G- > expressions, > and Git origins for main-distribution packages. > --- > gnu/local.mk | 3 +- > gnu/packages/chez-and-racket-bootstrap.scm | 15 +- > ...acket-gui-tethered-launcher-backport.patch | 26 + > gnu/packages/racket.scm | 1596 +++++++++++---- > -- > 4 files changed, 1118 insertions(+), 522 deletions(-) > create mode 100644 gnu/packages/patches/racket-gui-tethered- > launcher-backport.patch > > diff --git a/gnu/local.mk b/gnu/local.mk > index 5fcbe3a391..2fb4440eee 100644 > --- a/gnu/local.mk > +++ b/gnu/local.mk > @@ -41,7 +41,7 @@ > # Copyright © 2020 Vinicius Monego <monego@posteo.net> > # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> > # Copyright © 2021 Greg Hogan <code@greghogan.com> > -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> > +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> > # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> > # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> > # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> > @@ -1751,6 +1751,7 @@ dist_patch_DATA > = \ > %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ > %D%/packages/patches/rtags-separate- > rct.patch \ > %D%/packages/patches/racket-enable-scheme-backport.patch \ > + %D%/packages/patches/racket-gui-tethered-launcher- > backport.patch \ > %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ > %D%/packages/patches/remake-impure- > dirs.patch \ > %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ > diff --git a/gnu/packages/chez-and-racket-bootstrap.scm > b/gnu/packages/chez-and-racket-bootstrap.scm > index e837d49c63..b779099fb3 100644 > --- a/gnu/packages/chez-and-racket-bootstrap.scm > +++ b/gnu/packages/chez-and-racket-bootstrap.scm > @@ -46,7 +46,8 @@ (define-module (gnu packages chez-and-racket- > bootstrap) > #:use-module (gnu packages xorg) > #:use-module ((guix licenses) > #:prefix license:) Small note, #:prefix license: should be on the same line as #:use- module. > -(define %racket-version "8.4") > +(define %racket-version "8.4") ; MUST match "racket.scm" > +;; The definition of %racket-version is duplicated to avoid an > import cycle: > +;; see <https://issues.guix.gnu.org/53878#93>. > (define %chez-scheme-for-racket-version "9.5.7.3") > [...] > +(define %racket-version "8.4") ; MUST match "chez-and-racket- > bootstrap.scm" > +;; The definition of %racket-version is duplicated to avoid an > import cycle: > +;; see <https://issues.guix.gnu.org/53878#93>. > +(define %racket-commit > + (string-append "v" %racket-version)) That works, but it's not really nice. I did send my mail w.r.t. making the bootstrap packages procedures that take racket-version and origin as arguments before reading this mail, but I think my comment still applies mostly. WDYT? > +(define (extract-package-source origin spec) > + "Extract the source for a Racket package specified by SPEC from > ORIGIN into > +a new file-like object. In the resulting file-like object, the > package source > +will be in the directory \"/share/racket/pkgs/NAME/\", where NAME is > the Racket > +name for the package. > + > +SPEC is a list of the form: > + > + (NAME PATH) > + > +where PATH is the path to the package source relative to ORIGIN--- > possibly > +`\".\"`. As a special case, SPEC may also be given a string, which > is > +equivalent to: > + > + (NAME NAME) > + > +Examples: Would it make sense to use this procedure for our bootstrap packages already? (In particular for bootfiles or extracting chez-scheme from the racket source). Regarding the big racket package, the recipe currently looks a little nicer in that it no longer overrides `build', but I think we could still do a union-build with #:symlink copy-recursively if the full racket is just racket plus a bunch of packages on top. This would have the benefit that we could declare each of them as a package. Not sure if this is something we ought to address here or in a separate patch set, though. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4. 2022-02-20 10:16 ` Liliana Marie Prikler @ 2022-02-20 14:09 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-20 14:09 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, Ludovic Courtès, Liliana Marie Prikler Cc: Attila Lendvai, zimoun, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 4933 bytes --] On Sunday, February 20, 2022 5:16:04 AM EST Liliana Marie Prikler wrote: > > #:use-module (gnu packages xorg) > > #:use-module ((guix licenses) > > #:prefix license:) > > Small note, #:prefix license: should be on the same line as #:use- > module. > Ok. > > -(define %racket-version "8.4") > > +(define %racket-version "8.4") ; MUST match "racket.scm" > > +;; The definition of %racket-version is duplicated to avoid an > > import cycle: > > +;; see <https://issues.guix.gnu.org/53878#93>. > > (define %chez-scheme-for-racket-version "9.5.7.3") > > [...] > > +(define %racket-version "8.4") ; MUST match "chez-and-racket- > > bootstrap.scm" > > +;; The definition of %racket-version is duplicated to avoid an > > import cycle: > > +;; see <https://issues.guix.gnu.org/53878#93>. > > +(define %racket-commit > > + (string-append "v" %racket-version)) > > That works, but it's not really nice. I did send my mail w.r.t. making > the bootstrap packages procedures that take racket-version and origin > as arguments before reading this mail, but I think my comment still > applies mostly. WDYT? > As I said, I think that would cause an import cycle. This seems like a very subtle and confusing issue! I haven't heard anyone but Ludo’ express much confidence in their understanding of how this works—certainly I don't feel much! > > +(define (extract-package-source origin spec) > > + "Extract the source for a Racket package specified by SPEC from > > ORIGIN into > > +a new file-like object. In the resulting file-like object, the > > package source > > +will be in the directory \"/share/racket/pkgs/NAME/\", where NAME is > > the Racket > > +name for the package. > > + > > +SPEC is a list of the form: > > + > > + (NAME PATH) > > + > > +where PATH is the path to the package source relative to ORIGIN--- > > possibly > > +`\".\"`. As a special case, SPEC may also be given a string, which > > is > > +equivalent to: > > + > > + (NAME NAME) > > + > > > +Examples: > Would it make sense to use this procedure for our bootstrap packages > already? (In particular for bootfiles or extracting chez-scheme from > the racket source). > Well, for one thing, trying to use this package in "chez-and-racket- bootstrap.scm" seems like it could get us into trouble with import cycles again. I think it will be less painful if we can have at least "chez-and- racket-bootstrap.scm", "chez.scm", and "racket.scm" form a DAG. Also, this function was really intended to handle the quite common `?path=‹path›` case for Racket Git "package sources"[1]. Eventually, it should be part of a `racket-build-system`. > > Regarding the big racket package, the recipe currently looks a little > nicer in that it no longer overrides `build', but I think we could > still do a union-build with #:symlink copy-recursively if the full > racket is just racket plus a bunch of packages on top. This would have > the benefit that we could declare each of them as a package. Not sure > if this is something we ought to address here or in a separate patch > set, though. Well, I certainly do want to declare each of them as a package! But I don't know what the benefit would be for doing so before its possible for a Guix user to usefully, say, install one. Maybe you know this, but installing a Racket package isn't just a matter of putting a directory in the right place and setting a search path. Most obviously, it has to be compiled, and it would be most useful to explicitly generate "built packages"[2] separately from installing them into a layer. Installation into a layer potentially involves generating collection links files, indexing documentation cross-reference information, moving man pages or other kinds of files, creating launchers like the `drracket` command, and potentially various other steps: indeed, collections (not just packages) can specify arbitrary functions to be invoked by `raco setup` at pre-install, install, or post-install time. Creating a "config-tethered" layer—the kind we'd want to install into a Guix profile, as opposed to a sparse intermediate layer— also creates new `racket` and other executables in the layer's "bin" directory that exec the `racket` from the VM layer while propagating information about the layers that have been installed. Anyway, the packaging for racket@8.4 should be less of a hack than before (which was better than when we used to duplicate racket-minimal, VM and all), but this is all still fundamentally a hack, and I'd rather spend my effort trying to do the right thing, rather than overly fine-tuning the details of the temporary workarounds. -Philip [1]: https://docs.racket-lang.org/pkg/ Package_Concepts.html#%28part._concept~3asource%29 [2]: https://docs.racket-lang.org/pkg/strip.html [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (14 preceding siblings ...) 2022-02-20 6:06 ` [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 01/22] gnu: Use license prefix in (gnu packages racket) Philip McGrath ` (22 more replies) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 17 siblings, 23 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip Hi, I've been ruminating for a while on Liliana's comment from <https://issues.guix.gnu.org/53878#118>: On Wednesday, February 23, 2022 3:31:34 PM EST Liliana Marie Prikler wrote: > [...] there are some things that still > don't feel right for me – for instance the fact, that seemingly > unrelated modules now have to pull in racket bootstrap sounds like a > recipe for trouble. The final patch in the series also still does too > much for me to wrap my head around, which makes it difficult to audit. > > Therefore, one question I have w.r.t. updating Racket is whether we > could theoretically bump the version while keeping the old bootstrap, > and then adjust the bootstrap by adding all the packages you've made. > It does seem to be an all or nothing deal when doing the bootstrap > first, but that need not necessarily hold for bootstrap second. > > Also, accepting for a moment that we might have to move chez-scheme and > other important things into chez-scheme-and-racket-bootstrap (even > though I'm not really content with it), I still wonder if we could > introduce chez-scheme-for-system first (defined as simply chez-scheme > initially) and adjust the callers, then move chez-scheme while keeping > the function in chez.scm and finally do the magic with making it either > chez or racket. > It struck me that the core of the dependency cycle (at least, from one perspective) is that 'chez-scheme-for-racket' wants to 'inherit' from 'chez-scheme' but use '%racket-origin' for its 'source', and neither of those are thunked fields. I realized that, if we just pass the origin some other way than as the 'source' field, we can avoid adding the "chez-and-racket-bootstrap.scm" file altogether: patch v5 10/22 does the core of that. I also managed to split up the update to Racket 8.4 (patch v4 15/15) into a number of smaller steps (or, more precisely, rewrite it now that I knew what the end result would be). I now have the 'racket-minimal*' packages gradually evolve into the corresponding 'racket-vm-*' packages (rather than adding the 'racket-vm-*' stack in parallel), then split the new 'racket-minimal' package out of 'racket'. Hopefully this might be somewhat easier to review. The downside is there are now 22 patches, rather than 15. So, here is v5! -Philip P.S.: I've also posted this series at <https://gitlab.com/philip1/guix-patches/-/tags/guix-issue-53878-v5>. Philip McGrath (22): gnu: Use license prefix in (gnu packages racket). gnu: racket: Update to 8.4. gnu: racket: Use Git origins for Racket packages. gnu: racket-minimal: Use new package style. gnu: racket-minimal: Don't configure non-existant catalogs. gnu: racket-minimal: Change inheritance to follow bootstrapping. gnu: racket-minimal: Add "debug" output. gnu: make-installation-layer.rkt: Adjust indentation. gnu: racket-minimal: Separate from the Racket VM. gnu: racket: Move Chez bootfiles to (gnu packages chez). gnu: chez: Add utilities for Chez machine types. gnu: racket: Add 'racket-vm-for-system'. gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: chez-mit: Support chez-scheme-for-racket. gnu: Add chez-scheme-for-racket. gnu: chez: Add 'chez-scheme-for-system'. gnu: racket-vm-cs: Build with "--enable-scheme". gnu/local.mk | 4 +- gnu/packages/chez.scm | 1264 +++++++---- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- .../racket-enable-scheme-backport.patch | 465 ++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1866 ++++++++++++----- 7 files changed, 2774 insertions(+), 855 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 01/22] gnu: Use license prefix in (gnu packages racket). 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4 Philip McGrath ` (21 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (racket-minimal, racket-minimal-bc-3m, racket-bootstrap-chez-bootfiles): Use license prefix. --- gnu/packages/racket.scm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..ec9e836a4c 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -47,7 +45,8 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) #:prefix license:)) ;; Commentary: ;; @@ -254,7 +253,7 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) + (license (list license:asl2.0 license:expat)))) (define-public racket-minimal-bc-3m @@ -295,7 +294,7 @@ (define-public racket-minimal-bc-3m collector, 3M (``Moving Memory Manager'').") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) + (license (list license:lgpl3+ license:asl2.0 license:expat))))) (define-public racket-minimal-bc-cgc @@ -372,7 +371,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list asl2.0))))) + (license (list license:asl2.0))))) (define %installer-mirrors -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 01/22] gnu: Use license prefix in (gnu packages racket) Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:36 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages Philip McGrath ` (20 subsequent siblings) 22 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/patches/racket-enable-scheme-backport.patch, gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New patches. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/racket.scm (%racket-version): New variable. (%racket-commit): New variable. (%racket-origin): New variable. [patches]: Add "racket-enable-scheme-backport.patch". (racket-minimal): Update to 8.4. [version]: Use '%racket-version'. [source]: Use '%racket-origin'. [inputs]: Add 'ncurses'. Remove 'zlib:static' and 'lz4:static'. (racket-minimal-bc-3m)[inputs]: Adjust accordingly. (racket-bootstrap-chez-bootfiles)[version]: Use Chez Scheme's '(scheme-fork-version-number)'. (racket)[version]: Use '%racket-version'. [native-inputs]: Use '%racket-origin'. [source]: Update to 8.4. <patches>: Use "racket-gui-tethered-launcher-backport.patch". <snippet>: Remove "srfi-doc-nonfree". --- gnu/local.mk | 4 +- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 99 ++-- 4 files changed, 557 insertions(+), 37 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 98f2d4ac30..cf34905431 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1749,6 +1749,8 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..abf253486f --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/share/pkgs/gui-lib/mred/installer.rkt ++++ b/share/pkgs/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ec9e836a4c..00ec587eeb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -43,6 +43,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages libedit) #:use-module (gnu packages libffi) #:use-module (gnu packages multiprecision) + #:use-module (gnu packages ncurses) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) #:use-module (gnu packages xorg) @@ -95,6 +96,41 @@ (define-module (gnu packages racket) ;; ;; Code: +(define %racket-version "8.4") +;; ^ Remember to update racket-bootstrap-chez-bootfiles! +(define %racket-commit + (string-append "v" %racket-version)) +(define %racket-origin + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit %racket-commit))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" %racket-version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + (use-modules (guix build utils)) + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + ;; TODO: consider putting this in a (guix ...) or (guix build ...) + ;; module so it can be shared with the upstream Chez Scheme origin + ;; without cyclic issues. + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (define cfg-flag:sh-for-rktio `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" (assoc-ref %build-inputs "sh") @@ -128,41 +164,17 @@ (define src (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) + (version %racket-version) + (source %racket-origin) (inputs `(;; common to all racket-minimal variants: ("openssl" ,openssl) ("sqlite" ,sqlite) - ("sh" ,bash-minimal) + ("sh" ,bash-minimal) ;; <- for `system` + ("ncurses" ,ncurses) ;; <- for #%terminal ;; only for CS ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) + ("lz4" ,lz4))) (native-inputs `(("bootfiles" ,racket-bootstrap-chez-bootfiles) ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) @@ -263,9 +275,8 @@ (define-public racket-minimal-bc-3m (name "racket-minimal-bc-3m") (inputs (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) + (prepend libffi) ;; <- only for BC variants + (delete "zlib" "lz4"))) (native-inputs `(("libtool" ,libtool) ("racket" ,(if (%current-target-system) @@ -327,6 +338,11 @@ (define-public racket-bootstrap-chez-bootfiles (package (inherit racket-minimal) (name "racket-bootstrap-chez-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. (inputs `()) (native-inputs `(("racket" ,(if (%current-target-system) @@ -416,7 +432,7 @@ (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work + (version %racket-version) (source (origin (method url-fetch) @@ -425,7 +441,11 @@ (define-public racket %installer-mirrors)) (sha256 (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) + "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) (snippet #~(begin (use-modules (guix build utils) @@ -442,7 +462,14 @@ (define-public racket (with-directory-excursion "share/pkgs" (for-each delete-file-recursively '#+%main-repo-main-distribution-pkgs)) - #t)))) + ;; Minimal workaround for FSDG issue: + ;; see <https://github.com/racket/srfi/pull/15>. + ;; We will backport a better fix once we use Git + ;; origins for Racket packages. + (delete-file-recursively "share/pkgs/srfi-doc-nonfree") + (substitute* "share/pkgs/srfi/info.rkt" + (("\"srfi-doc-nonfree\"") + "")))))) (inputs `(("cairo" ,cairo) ("fontconfig" ,fontconfig) @@ -461,7 +488,7 @@ (define-public racket (native-inputs `(("racket" ,racket-minimal) ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + ("main-repo" ,%racket-origin))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-26 13:36 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 13:36 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-enable-scheme-backport.patch, > gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New > patches. > * gnu/local.mk (dist_patch_DATA): Add them. > * gnu/packages/racket.scm (%racket-version): New variable. > (%racket-commit): New variable. > (%racket-origin): New variable. > [patches]: Add "racket-enable-scheme-backport.patch". > (racket-minimal): Update to 8.4. > [version]: Use '%racket-version'. > [source]: Use '%racket-origin'. > [inputs]: Add 'ncurses'. Remove 'zlib:static' and 'lz4:static'. > (racket-minimal-bc-3m)[inputs]: Adjust accordingly. > (racket-bootstrap-chez-bootfiles)[version]: Use Chez Scheme's > '(scheme-fork-version-number)'. > (racket)[version]: Use '%racket-version'. > [native-inputs]: Use '%racket-origin'. > [source]: Update to 8.4. > <patches>: Use "racket-gui-tethered-launcher-backport.patch". > <snippet>: Remove "srfi-doc-nonfree". To be fair, I'm a little confused with the change in [native-inputs], but that is a minor commit message thing that I can fix up. Other than that looks pretty good to me. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 01/22] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:47 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style Philip McGrath ` (19 subsequent siblings) 22 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: Adjust path. * gnu/packages/racket.scm (extract-package-source, extract-package-source*): New procedures. (extend-layer): Rename to ... (make-installation-layer.rkt): ... this variable. Tweak command-line arguments. Adapt to 'config-tethered-apps-dir'. (racket): Stop inheriting from 'racket-minimal'. [version]: Use '%racket-version'. [source]: Stop using bundled tarball. [inputs]: Remove labels. Add 'racket-minimal' and package sources. [native-inputs]: Remove, since cross-compilation doesn't work yet. [arguments]: Rewrite to use G-expressions, package sources from 'inputs', an explicit 'install' phase, and the revised 'make-installation-layer.rkt'. --- ...acket-gui-tethered-launcher-backport.patch | 6 +- gnu/packages/racket.scm | 1151 ++++++++++++++--- 2 files changed, 975 insertions(+), 182 deletions(-) diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch index abf253486f..1e018eaa79 100644 --- a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -7,13 +7,13 @@ Related to racket/racket#4133 (cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) --- - share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + gui-lib/mred/installer.rkt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt index b1691472..9ef06c53 100644 ---- a/share/pkgs/gui-lib/mred/installer.rkt -+++ b/share/pkgs/gui-lib/mred/installer.rkt +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt @@ -72,4 +72,5 @@ (list "-A" (path->string (find-system-path 'addon-dir))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 00ec587eeb..9970dacedb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -28,7 +28,9 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -389,172 +391,939 @@ (define-public racket-bootstrap-chez-bootfiles Chez Scheme.") (license (list license:asl2.0))))) +(define (extract-package-source origin spec) + "Extract the source for a Racket package specified by SPEC from ORIGIN into +a new file-like object. In the resulting file-like object, the package source +will be in the directory \"/share/racket/pkgs/NAME/\", where NAME is the Racket +name for the package. -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) - -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) +SPEC is a list of the form: + (NAME PATH) + +where PATH is the path to the package source relative to ORIGIN---possibly +`\".\"`. As a special case, SPEC may also be given a string, which is +equivalent to: + + (NAME NAME) + +Examples: + + +- \"expeditor\" +- (\"main-distribution\" \".\") +- (\"racket-lib\" \"pkgs/racket-lib\")" + (match (match spec + ((? string? name) + (list name (file-append origin (string-append "/" name)))) + ((name ".") + (list name origin)) + ((name path) + (list name (file-append origin (string-append "/" path))))) + ((name src) + (computed-file + (string-append "racket-pkg-" name) + (with-imported-modules `((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p (string-append #$output "/share/racket/pkgs")) + (copy-recursively #$src (string-append #$output + "/share/racket/pkgs/" + #$name)))))))) + +(define (extract-package-source* source-groups) + "Return a list of file-like objects containing the sources of the Racket +packages specified by SOURCE-GROUPS, a list of the form: + + ((ORIGIN SPEC ...) ...) + +The result is equivalent to: + + (append (list (extract-package-source ORIGIN SPEC) ...) ...)" + (append-map (match-lambda + ((origin . specs) + (map (cut extract-package-source origin <>) + specs))) + source-groups)) (define-public racket (package - (inherit racket-minimal) (name "racket") (version %racket-version) - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) - (patches - ;; remove in Racket 8.5 - ;; see https://github.com/racket/racket/issues/4133 - (search-patches "racket-gui-tethered-launcher-backport.patch")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - ;; Minimal workaround for FSDG issue: - ;; see <https://github.com/racket/srfi/pull/15>. - ;; We will backport a better fix once we use Git - ;; origins for Racket packages. - (delete-file-recursively "share/pkgs/srfi-doc-nonfree") - (substitute* "share/pkgs/srfi/info.rkt" - (("\"srfi-doc-nonfree\"") - "")))))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,%racket-origin))) + (cons* + cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (extract-package-source* + `((,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/2d") + (commit %racket-commit))) + (sha256 (base32 + "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) + (file-name + (git-file-name "racket-2d" %racket-version))) + "2d" "2d-doc" "2d-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/algol60") + (commit %racket-commit))) + (sha256 (base32 + "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) + (file-name + (git-file-name "racket-algol60" %racket-version))) + ("algol60" ".")) + (,%racket-origin + ("base" "pkgs/base") ;; FIXME belongs in racket-minimal + ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/cext-lib") + (commit %racket-commit))) + (sha256 (base32 + "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) + (file-name (git-file-name "racket-cext-lib" %racket-version))) + "cext-lib" "dynext-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/class-iop") + (commit %racket-commit))) + (sha256 (base32 + "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l")) + (file-name (git-file-name "racket-class-iop" %racket-version))) + "class-iop-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/compatibility") + (commit "37f11132cdad7ef27386b68383d073f275d67c31"))) + (sha256 (base32 + "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0")) + (file-name + (git-file-name "racket-compatibility" %racket-version))) + "compatibility" "compatibility-doc" "compatibility-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/contract-profile") + (commit "95d980a076126b8e4e4284e912f2a7d9d3ab6860"))) + (sha256 (base32 + "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3")) + (file-name + (git-file-name "racket-contract-profile" %racket-version))) + ("contract-profile" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/data") + (commit "e32d012b394e32e102e8a9adfcc885bb0541ab51"))) + (sha256 (base32 + "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55")) + (file-name (git-file-name "racket-data" %racket-version))) + "data" "data-doc" "data-enumerate-lib" "data-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/datalog") + (commit "7d160a86451af8298093d07674a2eb0e1a0161a4"))) + (sha256 (base32 + "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp")) + (file-name (git-file-name "racket-datalog" %racket-version))) + ("datalog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/db") + (commit %racket-commit))) + (sha256 (base32 + "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5")) + (file-name (git-file-name "racket-db" %racket-version))) + "db" "db-doc" "db-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/deinprogramm") + (commit %racket-commit))) + (sha256 (base32 + "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd")) + (file-name + (git-file-name "racket-deinprogramm" %racket-version))) + "deinprogramm" "deinprogramm-signature") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/distributed-places") + (commit %racket-commit))) + (sha256 (base32 + "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0")) + (file-name + (git-file-name "racket-distributed-places" %racket-version))) + "distributed-places" + "distributed-places-doc" + "distributed-places-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/draw") + (commit %racket-commit))) + (sha256 (base32 + "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly")) + (file-name (git-file-name "racket-draw" %racket-version))) + "draw" "draw-doc" "draw-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/drracket") + (commit %racket-commit))) + (sha256 (base32 + "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c")) + (file-name (git-file-name "racket-drracket" %racket-version))) + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/ds-store") + (commit "949ca63dd00522b3ab8aec2d71c543ece8266872"))) + (sha256 (base32 + "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661")) + (file-name (git-file-name "racket-ds-store" %racket-version))) + "ds-store" "ds-store-doc" "ds-store-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eli-tester") + (commit "036e07d43a1f478ea1750881d5591d983ce1ffaf"))) + (sha256 (base32 + "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk")) + (file-name (git-file-name "racket-eli-tester" %racket-version))) + ("eli-tester" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/eopl") + (commit %racket-commit))) + (sha256 (base32 + "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s")) + (file-name (git-file-name "racket-eopl" %racket-version))) + ("eopl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/errortrace") + (commit %racket-commit))) + (sha256 (base32 + "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip")) + (file-name (git-file-name "racket-errortrace" %racket-version))) + "errortrace" "errortrace-doc" "errortrace-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/expeditor") + (commit %racket-commit))) + (sha256 (base32 + "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf")) + (file-name (git-file-name "racket-expeditor" %racket-version))) + "expeditor" "expeditor-doc" "expeditor-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/frtime") + (commit %racket-commit))) + (sha256 (base32 + "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5")) + (file-name (git-file-name "racket-frtime" %racket-version))) + ("frtime" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/future-visualizer") + (commit %racket-commit))) + (sha256 (base32 + "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm")) + (file-name + (git-file-name "racket-future-visualizer" %racket-version))) + "future-visualizer" + "future-visualizer-pict" + "future-visualizer-typed") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/games") + + (commit %racket-commit))) + (sha256 (base32 + "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d")) + (file-name (git-file-name "racket-games" %racket-version))) + ("games" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui-pkg-manager") + (commit %racket-commit))) + (sha256 (base32 + "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5")) + (file-name + (git-file-name "racket-gui-pkg-manager" %racket-version))) + "gui-pkg-manager-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/htdp") + (commit %racket-commit))) + (sha256 (base32 + "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl")) + (file-name (git-file-name "racket-htdp" %racket-version))) + "htdp" "htdp-doc" "htdp-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/html") + (commit %racket-commit))) + (sha256 (base32 + "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x")) + (file-name (git-file-name "racket-html" %racket-version))) + "html" "html-doc" "html-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/icons") + (commit %racket-commit))) + (sha256 (base32 + "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7")) + (file-name (git-file-name "racket-icons" %racket-version))) + ("icons" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/images") + (commit %racket-commit))) + (sha256 (base32 + "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl")) + (file-name (git-file-name "racket-images" %racket-version))) + "images" "images-doc" "images-gui-lib" "images-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/lazy") + (commit %racket-commit))) + (sha256 (base32 + "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf")) + (file-name (git-file-name "racket-lazy" %racket-version))) + ("lazy" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/macro-debugger") + (commit %racket-commit))) + (sha256 (base32 + "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm")) + (file-name + (git-file-name "racket-macro-debugger" %racket-version))) + "macro-debugger" "macro-debugger-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/main-distribution") + (commit %racket-commit))) + (sha256 (base32 + "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y")) + (file-name + (git-file-name "racket-main-distribution" %racket-version))) + ("main-distribution" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/make") + (commit %racket-commit))) + (sha256 (base32 + "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa")) + (file-name (git-file-name "racket-make" %racket-version))) + ("make" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/math") + (commit %racket-commit))) + (sha256 (base32 + "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac")) + (file-name (git-file-name "racket-math" %racket-version))) + "math" "math-doc" "math-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mysterx") + (commit %racket-commit))) + (sha256 (base32 + "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48")) + (file-name (git-file-name "racket-mysterx" %racket-version))) + ("mysterx" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzcom") + (commit %racket-commit))) + (sha256 (base32 + "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4")) + (file-name (git-file-name "racket-mzcom" %racket-version))) + ("mzcom" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/mzscheme") + (commit %racket-commit))) + (sha256 (base32 + "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9")) + (file-name (git-file-name "racket-mzscheme" %racket-version))) + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + ("optimization-coach" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/option-contract") + (commit %racket-commit))) + (sha256 (base32 + "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk")) + (file-name + (git-file-name "racket-option-contract" %racket-version))) + "option-contract" "option-contract-doc" "option-contract-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/parser-tools") + (commit %racket-commit))) + (sha256 (base32 + "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3")) + (file-name (git-file-name "racket-parser-tools" %racket-version))) + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pconvert") + (commit %racket-commit))) + (sha256 (base32 + "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1")) + (file-name (git-file-name "racket-pconvert" %racket-version))) + "pconvert-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict") + (commit %racket-commit))) + (sha256 (base32 + "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x")) + (file-name (git-file-name "racket-pict" %racket-version))) + "pict" "pict-doc" "pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/pict-snip") + (commit %racket-commit))) + (sha256 (base32 + "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x")) + (file-name (git-file-name "racket-pict-snip" %racket-version))) + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/picturing-programs") + (commit %racket-commit))) + (sha256 (base32 + "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr")) + (file-name + (git-file-name "racket-picturing-programs" %racket-version))) + ("picturing-programs" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plai") + (commit %racket-commit))) + (sha256 (base32 + "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl")) + (file-name (git-file-name "racket-plai" %racket-version))) + "plai" "plai-doc" "plai-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/planet") + (commit %racket-commit))) + (sha256 (base32 + "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9")) + (file-name (git-file-name "racket-planet" %racket-version))) + "planet" "planet-doc" "planet-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/plot") + (commit %racket-commit))) + (sha256 (base32 + "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7")) + (file-name (git-file-name "racket-plot" %racket-version))) + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/preprocessor") + (commit %racket-commit))) + (sha256 (base32 + "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg")) + (file-name (git-file-name "racket-preprocessor" %racket-version))) + ("preprocessor" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/profile") + (commit %racket-commit))) + (sha256 (base32 + "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb")) + (file-name (git-file-name "racket-profile" %racket-version))) + "profile" "profile-doc" "profile-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + ("quickscript" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r5rs") + (commit %racket-commit))) + (sha256 (base32 + "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6")) + (file-name (git-file-name "racket-r5rs" %racket-version))) + "r5rs" "r5rs-doc" "r5rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/r6rs") + (commit %racket-commit))) + (sha256 (base32 + "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4")) + (file-name (git-file-name "racket-r6rs" %racket-version))) + "r6rs" "r6rs-doc" "r6rs-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + ("racket-cheat" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racklog") + (commit %racket-commit))) + (sha256 (base32 + "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb")) + (file-name (git-file-name "racket-racklog" %racket-version))) + ("racklog" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/rackunit") + (commit %racket-commit))) + (sha256 (base32 + "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p")) + (file-name (git-file-name "racket-rackunit" %racket-version))) + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/readline") + (commit %racket-commit))) + (sha256 (base32 + "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn")) + (file-name (git-file-name "racket-readline" %racket-version))) + "readline" "readline-doc" "readline-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/realm") + (commit %racket-commit))) + (sha256 (base32 + "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi")) + (file-name (git-file-name "racket-realm" %racket-version))) + ("realm" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/redex") + (commit %racket-commit))) + (sha256 (base32 + "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f")) + (file-name (git-file-name "racket-redex" %racket-version))) + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sasl") + (commit %racket-commit))) + (sha256 (base32 + "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824")) + (file-name (git-file-name "racket-sasl" %racket-version))) + "sasl" "sasl-doc" "sasl-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scheme-lib") + (commit %racket-commit))) + (sha256 (base32 + "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x")) + (file-name (git-file-name "racket-scheme-lib" %racket-version))) + ("scheme-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/scribble") + (commit %racket-commit))) + (sha256 (base32 + "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm")) + (file-name (git-file-name "racket-scribble" %racket-version))) + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/serialize-cstruct-lib") + (commit %racket-commit))) + (sha256 (base32 + "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz")) + (file-name + (git-file-name "racket-serialize-cstruct-lib" %racket-version))) + ("serialize-cstruct-lib" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/sgl") + (commit %racket-commit))) + (sha256 (base32 + "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv")) + (file-name (git-file-name "racket-sgl" %racket-version))) + ("sgl" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/shell-completion") + (commit %racket-commit))) + (sha256 (base32 + "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj")) + (file-name + (git-file-name "racket-shell-completion" %racket-version))) + ("shell-completion" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/simple-tree-text-markup") + (commit %racket-commit))) + (sha256 (base32 + "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr")) + (file-name + (git-file-name "racket-simple-tree-text-markup" %racket-version))) + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slatex") + (commit "47e1d3e3e33d826bc2b26f9e8998eb235b23a9a5"))) + (sha256 (base32 + "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0")) + (file-name (git-file-name "racket-slatex" %racket-version))) + ("slatex" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/slideshow") + (commit %racket-commit))) + (sha256 (base32 + "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm")) + (file-name (git-file-name "racket-slideshow" %racket-version))) + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" + "slideshow-plugin") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/snip") + (commit %racket-commit))) + (sha256 (base32 + "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj")) + (file-name (git-file-name "racket-snip" %racket-version))) + "snip" "snip-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/typed-racket") + (commit %racket-commit))) + (sha256 (base32 + "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv")) + (file-name (git-file-name "racket-typed-racket" %racket-version))) + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/string-constants") + (commit %racket-commit))) + (sha256 (base32 + "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6")) + (file-name + (git-file-name "racket-string-constants" %racket-version))) + "string-constants" "string-constants-doc" "string-constants-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/swindle") + (commit %racket-commit))) + (sha256 (base32 + "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67")) + (file-name (git-file-name "racket-swindle" %racket-version))) + ("swindle" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/syntax-color") + (commit %racket-commit))) + (sha256 (base32 + "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp")) + (file-name (git-file-name "racket-syntax-color" %racket-version))) + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/trace") + (commit %racket-commit))) + (sha256 (base32 + "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia")) + (file-name (git-file-name "racket-trace" %racket-version))) + ("trace" ".")) + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/unix-socket") + (commit %racket-commit))) + (sha256 (base32 + "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y")) + (file-name (git-file-name "racket-unix-socket" %racket-version))) + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/web-server") + (commit %racket-commit))) + (sha256 (base32 + "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn")) + (file-name (git-file-name "racket-web-server" %racket-version))) + "web-server" "web-server-doc" "web-server-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/wxme") + (commit %racket-commit))) + (sha256 (base32 + "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b")) + (file-name (git-file-name "racket-wxme" %racket-version))) + "wxme" "wxme-lib") + (,(origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/xrepl") + (commit %racket-commit))) + (sha256 (base32 + "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) + (file-name (git-file-name "racket-xrepl" %racket-version))) + "xrepl" "xrepl-doc" "xrepl-lib"))))) + (build-system gnu-build-system) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + ;; We're using #:configure-flags to pass flags for + ;; `make-installation-layer.rkt` and #:make-flags to pass arguments for + ;; `raco pkg install`. + (list + #:configure-flags + #~`("--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit"))))) + #:make-flags #~`("main-distribution") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((racket (search-input-file inputs "bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@configure-flags + ,(dirname (dirname racket)) + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket (search-input-file inputs "/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -564,17 +1333,20 @@ (define dest (string-append pkgs-dir "/" pkg)) The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) -(define extend-layer +(define make-installation-layer.rkt (scheme-file - "extend-layer.rkt" + "make-installation-layer.rkt" `(module - extend-layer racket/base + make-installation-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) (define config-file-pth @@ -584,8 +1356,14 @@ (define (build-path-string . args) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define extra-foreign-lib-search-dirs '()) (command-line - #:args (parent-layer prefix . lib-dir*) + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) (let* ([config (for/fold ([config (file->value (build-path parent-layer @@ -615,27 +1393,42 @@ (define rx:racket (build-path-string parent-layer pth)) (filter values (hash-ref config search-key null)))))] [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config - 'lib-search-dirs - (append rkt - lib-dir* - extra)))] + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] [bin-dir (hash-ref config 'bin-dir)] [config (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) 'config-tethered-console-bin-dir bin-dir 'config-tethered-gui-bin-dir bin-dir)] [new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages Philip McGrath @ 2022-02-26 13:47 ` Liliana Marie Prikler 2022-02-26 14:20 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 13:47 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: > Adjust path. > * gnu/packages/racket.scm (extract-package-source, > extract-package-source*): New procedures. > (extend-layer): Rename to ... > (make-installation-layer.rkt): ... this variable. Tweak command-line > arguments. Adapt to 'config-tethered-apps-dir'. > (racket): Stop inheriting from 'racket-minimal'. > [version]: Use '%racket-version'. > [source]: Stop using bundled tarball. > [inputs]: Remove labels. Add 'racket-minimal' and package sources. > [native-inputs]: Remove, since cross-compilation doesn't work yet. > [arguments]: Rewrite to use G-expressions, package sources from > 'inputs', an explicit 'install' phase, and the revised > 'make-installation-layer.rkt'. Since you haven't made this a union-build yet, I will from now on assume that it is indeed more complicated than one to save us some time debating whether it should or shouldn't be. Given that this was my main complaint w.r.t. the stuff following make-installation-layer, much is now resolved, except for two things. First, can we simplify "make-installation-layer.rkt" to "make- installation-layer"? I don't think the file extension conveys much meaning here, or does it? Second, can we find an abbreviation for > + (extract-package-source* > + `((,(origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/racket/2d") > + (commit %racket-commit))) > + (sha256 (base32 > + > "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) > + (file-name > + (git-file-name "racket-2d" %racket-version))) > + "2d" "2d-doc" "2d-lib") > + (,(origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/racket/algol60") > + (commit %racket-commit))) > + (sha256 (base32 > + > "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) > + (file-name > + (git-file-name "racket-algol60" %racket-version))) > + ("algol60" ".")) > + (,%racket-origin > + ("base" "pkgs/base") ;; FIXME belongs in racket-minimal > + ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in > racket-minimal > + ("at-exp-lib" "pkgs/at-exp-lib") > + ("compiler" "pkgs/compiler") > + ("compiler-lib" "pkgs/compiler-lib") > + ("net" "pkgs/net") > + ("net-doc" "pkgs/net-doc") > + ("net-lib" "pkgs/net-lib") > + ("racket-doc" "pkgs/racket-doc") > + ("racket-index" "pkgs/racket-index") > + ("sandbox-lib" "pkgs/sandbox-lib") > + ("zo-lib" "pkgs/zo-lib")) > + (,(origin > + (method git-fetch) > + (uri (git-reference > + (url "https://github.com/racket/cext-lib") > + (commit %racket-commit))) > + (sha256 (base32 > + > "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) > + (file-name (git-file-name "racket-cext-lib" %racket- > version))) > + "cext-lib" "dynext-lib") > [...] I think some way to shorten those origins would do wonders in terms of the number of lines this patch adds. Other than that, looks pretty good to me. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 13:47 ` Liliana Marie Prikler @ 2022-02-26 14:20 ` Philip McGrath 2022-02-26 14:26 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 14:20 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 3457 bytes --] Hi, On Saturday, February 26, 2022 8:47:45 AM EST Liliana Marie Prikler wrote: > First, can we simplify "make-installation-layer.rkt" to "make- > installation-layer"? I don't think the file extension conveys much > meaning here, or does it? To me (I don't know about anyone else), the ".rtk" extension tells me that I have to pass the file as an argument to `racket`, i.e. that the file is not a launcher from `raco exe` or a script with a shebang that I could `invoke` directly. > > Second, can we find an abbreviation for > > > + (extract-package-source* > > + `((,(origin > > + (method git-fetch) > > + (uri (git-reference > > + (url "https://github.com/racket/2d") > > + (commit %racket-commit))) > > + (sha256 (base32 > > + > > "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) > > + (file-name > > + (git-file-name "racket-2d" %racket-version))) > > + "2d" "2d-doc" "2d-lib") > > + (,(origin > > + (method git-fetch) > > + (uri (git-reference > > + (url "https://github.com/racket/algol60") > > + (commit %racket-commit))) > > + (sha256 (base32 > > + > > "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx")) > > + (file-name > > + (git-file-name "racket-algol60" %racket-version))) > > + ("algol60" ".")) > > + (,%racket-origin > > + ("base" "pkgs/base") ;; FIXME belongs in racket-minimal > > + ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in > > racket-minimal > > + ("at-exp-lib" "pkgs/at-exp-lib") > > + ("compiler" "pkgs/compiler") > > + ("compiler-lib" "pkgs/compiler-lib") > > + ("net" "pkgs/net") > > + ("net-doc" "pkgs/net-doc") > > + ("net-lib" "pkgs/net-lib") > > + ("racket-doc" "pkgs/racket-doc") > > + ("racket-index" "pkgs/racket-index") > > + ("sandbox-lib" "pkgs/sandbox-lib") > > + ("zo-lib" "pkgs/zo-lib")) > > + (,(origin > > + (method git-fetch) > > + (uri (git-reference > > + (url "https://github.com/racket/cext-lib") > > + (commit %racket-commit))) > > + (sha256 (base32 > > + > > "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341")) > > + (file-name (git-file-name "racket-cext-lib" %racket- > > version))) > > + "cext-lib" "dynext-lib") > > [...] > > I think some way to shorten those origins would do wonders in terms of > the number of lines this patch adds. > At one point, I had abbreviated the origins as something like: (REPO-SPEC SHA256 [COMMIT]) where REPO-SPEC is one of: (GITHUB-OWNER GITHUB-REPO) ; ^ e.g. for https://github.com/RenaissanceBug/racket-cookies GITHUB-REPO ; "racket" is owner and COMMIT defaults to `%racket-commit`, but could be overridden for <https://github.com/racket/srfi>. I think I'd given SHA256 as a literal string, but it could be e.g.: (extract-package-source* `((("2d" ,(base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) "2d" "2d-doc" "2d-lib") ...)) if that seems better. I wasn't sure about the trade-off between being slightly more cryptic than explicit origins, but a lot shorter. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 14:20 ` Philip McGrath @ 2022-02-26 14:26 ` Liliana Marie Prikler 2022-02-26 17:23 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 14:26 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 09:20 -0500 schrieb Philip McGrath: > Hi, > > On Saturday, February 26, 2022 8:47:45 AM EST Liliana Marie Prikler > wrote: > > First, can we simplify "make-installation-layer.rkt" to "make- > > installation-layer"? I don't think the file extension conveys much > > meaning here, or does it? > > To me (I don't know about anyone else), the ".rtk" extension tells me > that I have to pass the file as an argument to `racket`, i.e. that > the file is not a launcher from `raco exe` or a script with a shebang > that I could `invoke` directly. I'm not talking about the generated file, but the procedure that generates it. Special characters like dots and slash are still pretty special in Scheme, even if they're allowed as identifiers. > > I think some way to shorten those origins would do wonders in terms > > of the number of lines this patch adds. > > > > At one point, I had abbreviated the origins as something like: > > (REPO-SPEC SHA256 [COMMIT]) > > where REPO-SPEC is one of: > > (GITHUB-OWNER GITHUB-REPO) > ; ^ e.g. for https://github.com/RenaissanceBug/racket-cookies > GITHUB-REPO ; "racket" is owner > > and COMMIT defaults to `%racket-commit`, but could be overridden for > <https://github.com/racket/srfi>. > > I think I'd given SHA256 as a literal string, but it could be e.g.: > > (extract-package-source* > `((("2d" ,(base32 > "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr")) > "2d" "2d-doc" "2d-lib") > ...)) I wouldn't do this inside of extract-package-source, but define a one or two liner for adding specifically packages hosted on racket's github. WDYT? > I wasn't sure about the trade-off between being slightly more cryptic > than explicit origins, but a lot shorter. Note that the goal is not to code golf, but to be understandable. When adding a bunch of origins as inputs, understandability suffers by induced scrolling. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 14:26 ` Liliana Marie Prikler @ 2022-02-26 17:23 ` Philip McGrath 2022-02-26 18:30 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 17:23 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Liliana Marie Prikler, raingloom, Attila Lendvai, Malte Gerdes [-- Attachment #1: Type: text/plain, Size: 3097 bytes --] Hi, On Saturday, February 26, 2022 9:26:29 AM EST Liliana Marie Prikler wrote: > Am Samstag, dem 26.02.2022 um 09:20 -0500 schrieb Philip McGrath: > > On Saturday, February 26, 2022 8:47:45 AM EST Liliana Marie Prikler > > > > wrote: > > > First, can we simplify "make-installation-layer.rkt" to "make- > > > installation-layer"? I don't think the file extension conveys much > > > meaning here, or does it? > > > > To me (I don't know about anyone else), the ".rtk" extension tells me > > that I have to pass the file as an argument to `racket`, i.e. that > > the file is not a launcher from `raco exe` or a script with a shebang > > that I could `invoke` directly. > > I'm not talking about the generated file, but the procedure that > generates it. Special characters like dots and slash are still pretty > special in Scheme, even if they're allowed as identifiers. > Do you mean A, B, C, and/or D of these: a > (replace 'configure > (lambda* (#:key inputs configure-flags #:allow-other-keys) > (let* ((racket (search-input-file inputs "bin/racket"))) > (apply invoke > racket > #$make-installation-layer.rkt ;; <--- A > `(,@configure-flags > ,(dirname (dirname racket)) > ,#$output)) > (invoke racket > "--config" (string-append #$output "/etc/racket") > "-l" "raco" "setup" > "--no-user")))) > > [...] > > (define make-installation-layer.rkt ;; <--- B > (scheme-file > "make-installation-layer.rkt" ;; <--- C > `(module > make-installation-layer racket/base ;; <--- D > (require racket/cmdline or something else? In particular, not to be dense, but B is not a function. One of the reasons I particularly like being able to use `.` in identifiers is to refer to files by name, without some ad-hoc encoding. > > > I think some way to shorten those origins would do wonders in terms > > > of the number of lines this patch adds. > > > > At one point, I had abbreviated the origins as something like: > > > > (REPO-SPEC SHA256 [COMMIT]) > > > > [...] > > I wouldn't do this inside of extract-package-source, but define a one > or two liner for adding specifically packages hosted on racket's > github. WDYT? > > > I wasn't sure about the trade-off between being slightly more cryptic > > than explicit origins, but a lot shorter. > > Note that the goal is not to code golf, but to be understandable. When > adding a bunch of origins as inputs, understandability suffers by > induced scrolling. > I've done this, and it was a very good idea. In particular, it helped find some places where I hadn't switched to using `%racket-commit` once the release was tagged. Other than potentially doing something about "make-installation-layer.rkt", I'd plan to squash the WIP/FIXUP commits in <https://gitlab.com/philip1/guix-patches/-/tree/racket-chez-refactor-hist-28> and send it as v6. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 17:23 ` Philip McGrath @ 2022-02-26 18:30 ` Liliana Marie Prikler 2022-02-26 19:55 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 18:30 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 12:23 -0500 schrieb Philip McGrath: > Hi, > > On Saturday, February 26, 2022 9:26:29 AM EST Liliana Marie Prikler > wrote: > > I'm not talking about the generated file, but the procedure that > > generates it. Special characters like dots and slash are still > > pretty special in Scheme, even if they're allowed as identifiers. > > Do you mean A, B, C, and/or D of these: > a > > (replace 'configure > > (lambda* (#:key inputs configure-flags #:allow-other- > > keys) > > (let* ((racket (search-input-file inputs > > "bin/racket"))) > > (apply invoke > > racket > > #$make-installation-layer.rkt ;; <--- A > > `(,@configure-flags > > ,(dirname (dirname racket)) > > ,#$output)) > > (invoke racket > > "--config" (string-append #$output > > "/etc/racket") > > "-l" "raco" "setup" > > "--no-user")))) > > > > [...] > > > > (define make-installation-layer.rkt ;; <--- B > > (scheme-file > > "make-installation-layer.rkt" ;; <--- C > > `(module > > make-installation-layer racket/base ;; <--- D > > (require racket/cmdline > > or something else? The name in B is confusing imo, because it implies a procedure when it is in fact a file. Of course, that'd affect A as well. The file name in C does not matter too much, but should probably be matched with B to some extent (but importantly keeping the .rkt extension even if we drop it from B). I'm not sure if D is a function call or not, but if it's a module name perhaps we should make it match B. Given that we pass configure-flags to this thing, how about "configure- racket-layer", "configure-layer.rkt" or something along those lines? > In particular, not to be dense, but B is not a function. Yeah, that's my bad for only skimming these and not paying too close attention to brackets. The name itself implies a function, hence my confusion. Looking at things closely would make me see more typos like ";; workaroung Guile reader/printer:" workaround. > One of the reasons I particularly like being able to use `.` in > identifiers is to refer to files by name, without some ad-hoc > encoding. I do admit that is helpful, but in this context, metaphors were mixed in a way that conveyed the wrong message. > > > > I think some way to shorten those origins would do wonders in > > > > terms > > > > of the number of lines this patch adds. > > > > > > At one point, I had abbreviated the origins as something like: > > > > > > (REPO-SPEC SHA256 [COMMIT]) > > > > > > [...] > > > > I wouldn't do this inside of extract-package-source, but define a > > one or two liner for adding specifically packages hosted on > > racket's github. WDYT? > > > > > I wasn't sure about the trade-off between being slightly more > > > cryptic > > > than explicit origins, but a lot shorter. > > > > Note that the goal is not to code golf, but to be understandable. > > When adding a bunch of origins as inputs, understandability suffers > > by induced scrolling. > > > > I've done this, and it was a very good idea. In particular, it helped > find some places where I hadn't switched to using `%racket-commit` > once the release was tagged. That is better, but can still be improved. As hinted at in my comment to your tree, origin snippets might be a better solution here unless I'm missing something in the heat of the moment. > Other than potentially doing something about "make-installation- > layer.rkt", > I'd plan to squash the WIP/FIXUP commits in > < > https://gitlab.com/philip1/guix-patches/-/tree/racket-chez-refactor-hist-28 > > > and send it as v6. I did have a short look at it and apart from the above comment it appears fine, but I'll have to reevaluate it when it's a full v6 anyway. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 18:30 ` Liliana Marie Prikler @ 2022-02-26 19:55 ` Philip McGrath 2022-02-26 21:09 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 19:55 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 4684 bytes --] On Saturday, February 26, 2022 1:30:08 PM EST Liliana Marie Prikler wrote: > Hi, > > Am Samstag, dem 26.02.2022 um 12:23 -0500 schrieb Philip McGrath: > > Hi, > > > > On Saturday, February 26, 2022 9:26:29 AM EST Liliana Marie Prikler > > > > wrote: > > > I'm not talking about the generated file, but the procedure that > > > generates it. Special characters like dots and slash are still > > > pretty special in Scheme, even if they're allowed as identifiers. > > > > Do you mean A, B, C, and/or D of these: > > a > > > > > (replace 'configure > > > (lambda* (#:key inputs configure-flags #:allow-other- > > > keys) > > > (let* ((racket (search-input-file inputs > > > "bin/racket"))) > > > (apply invoke > > > racket > > > #$make-installation-layer.rkt ;; <--- A > > > `(,@configure-flags > > > ,(dirname (dirname racket)) > > > ,#$output)) > > > (invoke racket > > > "--config" (string-append #$output > > > "/etc/racket") > > > "-l" "raco" "setup" > > > "--no-user")))) > > > > > > [...] > > > > > > (define make-installation-layer.rkt ;; <--- B > > > (scheme-file > > > "make-installation-layer.rkt" ;; <--- C > > > `(module > > > make-installation-layer racket/base ;; <--- D > > > (require racket/cmdline > > > > or something else? > > The name in B is confusing imo, because it implies a procedure when it > is in fact a file. Of course, that'd affect A as well. The file name > in C does not matter too much, but should probably be matched with B to > some extent (but importantly keeping the .rkt extension even if we drop > it from B). I'm not sure if D is a function call or not, but if it's a > module name perhaps we should make it match B. > > Given that we pass configure-flags to this thing, how about "configure- > racket-layer", "configure-layer.rkt" or something along those lines? > "configure-layer.rkt" seems fine. I do see the potential for confusion about whether this was "making" an "installation-layer.rkt". (D is a module name and should for clarity match C without the suffix. Ultimately, for a module that is not a submodule, it is ignored and the name comes from context. This is an older way of writing modules that predates "#lang" (which would be inconvenient with `scheme-file`). Calling `read` with the appropriate parameters on the input "#lang racket/base 42" would produce the datum `(module anonymous-module racket/base (#%module-begin 42))`.) > > In particular, not to be dense, but B is not a function. > > Yeah, that's my bad for only skimming these and not paying too close > attention to brackets. The name itself implies a function, hence my > confusion. Looking at things closely would make me see more typos like > ";; workaroung Guile reader/printer:" > workaround. > Thanks. > > > > > I think some way to shorten those origins would do wonders in > > > > > terms > > > > > of the number of lines this patch adds. > > > > > > > > At one point, I had abbreviated the origins as something like: > > > > > > > > (REPO-SPEC SHA256 [COMMIT]) > > > > > > > > [...] > > > > > > I wouldn't do this inside of extract-package-source, but define a > > > one or two liner for adding specifically packages hosted on > > > racket's github. WDYT? > > > > > > > I wasn't sure about the trade-off between being slightly more > > > > cryptic > > > > than explicit origins, but a lot shorter. > > > > > > Note that the goal is not to code golf, but to be understandable. > > > When adding a bunch of origins as inputs, understandability suffers > > > by induced scrolling. > > > > I've done this, and it was a very good idea. In particular, it helped > > find some places where I hadn't switched to using `%racket-commit` > > once the release was tagged. > > That is better, but can still be improved. As hinted at in my comment > to your tree, origin snippets might be a better solution here unless > I'm missing something in the heat of the moment. Could you give an example of what you imagine the result might look like in use? E.g. (but I'm not sure this would really be an improvement): > (cons* > ... > libedit > racket-minimal > (append > (racket-package-sources > "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") > "2d" "2d-doc" "2d-lib") > (racket-package-sources > "algol60" (base32 "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx") > '("algol60" ".")) > ...)) -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages. 2022-02-26 19:55 ` Philip McGrath @ 2022-02-26 21:09 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 21:09 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 14:55 -0500 schrieb Philip McGrath: > "configure-layer.rkt" seems fine. I do see the potential for confusion > about whether this was "making" an "installation-layer.rkt". configure-layer.rkt it is then :) > > > > > > I think some way to shorten those origins would do wonders in > > > > > > terms of the number of lines this patch adds. > > > > > > > > > > At one point, I had abbreviated the origins as something like: > > > > > > > > > > (REPO-SPEC SHA256 [COMMIT]) > > > > > > > > > > [...] > > > > > > > > I wouldn't do this inside of extract-package-source, but define a > > > > one or two liner for adding specifically packages hosted on > > > > racket's github. WDYT? > > > > > > > > > I wasn't sure about the trade-off between being slightly more > > > > > cryptic > > > > > than explicit origins, but a lot shorter. > > > > > > > > Note that the goal is not to code golf, but to be understandable. > > > > When adding a bunch of origins as inputs, understandability > > > > suffers > > > > by induced scrolling. > > > > > > I've done this, and it was a very good idea. In particular, it > > > helped > > > find some places where I hadn't switched to using `%racket-commit` > > > once the release was tagged. > > > > That is better, but can still be improved. As hinted at in my > > comment > > to your tree, origin snippets might be a better solution here unless > > I'm missing something in the heat of the moment. > > Could you give an example of what you imagine the result might look > like in use? E.g. (but I'm not sure this would really be an > improvement): > > > (cons* > > ... > > libedit > > racket-minimal > > (append > > (racket-package-sources > > "2d" (base32 > > "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") > > "2d" "2d-doc" "2d-lib") > > (racket-package-sources > > "algol60" (base32 > > "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx") > > '("algol60" ".")) > > ...)) I'd write this as --8<---------------cut here---------------start------------->8--- (list ... libedit racket-minimal (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") '("2d" "2d-doc" "2d-lib") (simple-racket-origin "algol60" (base32 "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx") '("algol60" ".") ...) --8<---------------cut here---------------end--------------->8--- I do wonder whether these packages can further be modularized (i.e. so that they build as packages) with configure-layer.rkt acting as a profile hook and some racket meta package simply adding racket-minimal and all the base stuff into the profile, but for now let's just have an easy way of formulating origins. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 14:14 ` Liliana Marie Prikler 2022-06-13 7:35 ` Maxime Devos 2022-02-26 13:02 ` [bug#53878] [PATCH v5 05/22] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath ` (18 subsequent siblings) 22 siblings, 2 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (cfg-flag:sh-for-rktio, cfg-flag:enable-lt, cfg-glag:enable-racket): Change to G-expressions and combine in ... (racket-vm-common-configure-flags): ... this new thunk. (unpack-nanopass+stex): Change to G-expression and move to ... (make-unpack-nanopass+stex): ... this new thunk. (racket-bootstrap-chez-bootfiles): Rename to ... (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable, and stop inheriting from 'racket-minimal'. [native-inputs]: Remove labels. [build-system]: Use 'copy-build-system'. [arguments]: Use G-expressions. Install under "lib". (racket-minimal)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. Avoid 'assoc-ref'. Adapt to changes in 'chez-scheme-for-racket-bootstrap-bootfiles'. (racket-minimal-bc-3m)[native-inputs]: Remove labels. [arguments]: Use G-expressions. (racket-minimal-bc-cgc)[native-inputs]: Remove labels. [arguments]: Use G-expressions. --- gnu/packages/racket.scm | 332 ++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 169 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 9970dacedb..55514148cb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -26,6 +26,7 @@ (define-module (gnu packages racket) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) @@ -99,7 +100,7 @@ (define-module (gnu packages racket) ;; Code: (define %racket-version "8.4") -;; ^ Remember to update racket-bootstrap-chez-bootfiles! +;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin @@ -133,34 +134,42 @@ (define %racket-origin ;; Unbundle libffi. (delete-file-recursively "racket/src/bc/foreign/libffi"))))) -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) +(define (racket-vm-common-configure-flags) + ;; under a lambda abstraction to avoid evaluating bash-minimal too early. + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")))) -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) +(define (make-unpack-nanopass+stex) + ;; Adapted from chez-scheme. + ;; TODO: Refactor enough to share this directly. + ;; Thunked to avoid evaliating 'chez-scheme' too early. + #~(begin + (copy-recursively + #$(match (assoc-ref (package-native-inputs chez-scheme) + "nanopass") + ((src) + src)) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) (define-public racket-minimal @@ -169,91 +178,87 @@ (define-public racket-minimal (version %racket-version) (source %racket-origin) (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) ;; <- for `system` - ("ncurses" ,ncurses) ;; <- for #%terminal - ;; only for CS - ("zlib" ,zlib) - ("lz4" ,lz4))) + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for CS + zlib + lz4)) (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (list chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m)) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) + (list + #:configure-flags + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) (guix build gnu-build-system) (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))) + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs + . (,(string-append + "https://download.racket-lang.org/releases/" + #$(package-version this-package) + "/catalog/") + #f)))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -269,7 +274,6 @@ (define (write-racket-hash alist) ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) - (define-public racket-minimal-bc-3m (hidden-package (package @@ -280,21 +284,19 @@ (define-public racket-minimal-bc-3m (prepend libffi) ;; <- only for BC variants (delete "zlib" "lz4"))) (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) + (list libtool + (if (%current-target-system) + racket-minimal + racket-minimal-bc-cgc))) (arguments (substitute-keyword-arguments (package-arguments racket-minimal) ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))) + ((#:phases cs-phases) + #~(modify-phases #$cs-phases + (delete 'unpack-nanopass+stex) + (delete 'unpack-bootfiles))))) (synopsis "Minimal Racket with the BC [3M] runtime system") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written @@ -309,19 +311,16 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) - (define-public racket-minimal-bc-cgc (package (inherit racket-minimal-bc-3m) (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) + (native-inputs (list libtool)) (arguments (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags))))) (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or ``bytecode'') implementation is not recommended for general use. It uses @@ -334,47 +333,42 @@ (define-public racket-minimal-bc-cgc also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector."))) - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source %racket-origin) + (inputs `()) + (native-inputs (list racket-minimal-bc-3m)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$(make-unpack-nanopass+stex))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/bin/racket") + "rktboot/main.rkt")))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it requires ``bootfiles'' containing the Scheme-implemented portions compiled for the current platform. (Chez can then cross-compile bootfiles for all other supported platforms.) @@ -389,7 +383,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list license:asl2.0))))) + (license (list license:asl2.0)))) (define (extract-package-source origin spec) "Extract the source for a Racket package specified by SPEC from ORIGIN into -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style Philip McGrath @ 2022-02-26 14:14 ` Liliana Marie Prikler 2022-02-26 14:22 ` Philip McGrath 2022-06-13 7:35 ` Maxime Devos 1 sibling, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 14:14 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > +(define (make-unpack-nanopass+stex) > + ;; Adapted from chez-scheme. > + ;; TODO: Refactor enough to share this directly. > + ;; Thunked to avoid evaliating 'chez-scheme' too early. evaluating. Also, I think the thunked part should go above the TODO, WDYT? Other than that LGTM ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style. 2022-02-26 14:14 ` Liliana Marie Prikler @ 2022-02-26 14:22 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 14:22 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 524 bytes --] Hi, On Saturday, February 26, 2022 9:14:13 AM EST Liliana Marie Prikler wrote: > Hi, > > Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > > +(define (make-unpack-nanopass+stex) > > + ;; Adapted from chez-scheme. > > + ;; TODO: Refactor enough to share this directly. > > + ;; Thunked to avoid evaliating 'chez-scheme' too early. > > evaluating. Yes, thanks. > Also, I think the thunked part should go above the TODO, WDYT? > I don't mind either way. This is removed in v5 17/22, anyway. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style Philip McGrath 2022-02-26 14:14 ` Liliana Marie Prikler @ 2022-06-13 7:35 ` Maxime Devos 1 sibling, 0 replies; 214+ messages in thread From: Maxime Devos @ 2022-06-13 7:35 UTC (permalink / raw) To: Philip McGrath, 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 277 bytes --] Adding (ice-9 exceptions) to the imports caused a bug: https://issues.guix.gnu.org/54546 (resending because #53878 was archived) (re-sending the re-send because debbugs again said it was read-only even though I sent the unarchive message.) Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 05/22] gnu: racket-minimal: Don't configure non-existant catalogs. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath ` (17 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (racket-minimal)[arguments]<#:phases>: Change 'initialize-config.rktd' to only add a release catalog when the package version is a release version. --- gnu/packages/racket.scm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 55514148cb..abcd9658b2 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -231,6 +231,15 @@ (define (write-racket-hash alist) (format #t "(~s . ~s)" k v))) alist) (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) (mkdir-p "racket/etc") (with-output-to-file "racket/etc/config.rktd" (lambda () @@ -239,12 +248,8 @@ (define (write-racket-hash alist) . (#f #$(file-append (this-package-input "openssl") "/lib") #$(file-append (this-package-input "sqlite") "/lib"))) (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - #$(package-version this-package) - "/catalog/") - #f)))))))) + (catalogs ,@maybe-release-catalog + #f))))))) (add-before 'configure 'chdir (lambda _ (chdir "racket/src"))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 05/22] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 14:19 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 07/22] gnu: racket-minimal: Add "debug" output Philip McGrath ` (16 subsequent siblings) 22 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip Having the package inheritance chain go in the same direction as the bootstrapping chain, rather than the opposite, is less confusing. In some cases, it can also help to avoid unnecessary rebuilds. * gnu/packages/racket.scm (racket-minimal-bc-cgc): Change to be the root of the package inheritance chain. [version, source, inputs, native-inputs, build-system, arguments, home-page, license]: Inline formerly inherited values. (racket-minimal-bc-3m): Inherit from 'racket-minimal-bc-cgc' rather than 'racket-minimal'. [inputs, native-inputs, arguments, license]: Adjust accordingly. (racket-minimal): Inherit from 'racket-minimal-bc-3m'. [inputs, native-inputs, arguments, license]: Adjust accordingly. [properties]: Override effect of 'hidden-package'. --- gnu/packages/racket.scm | 294 ++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index abcd9658b2..f5a8091be0 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -172,99 +172,157 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) +(define-public racket-minimal-bc-cgc + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-minimal-bc-cgc") + (version %racket-version) + (source %racket-origin) + (inputs + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for BC variants: + libffi)) + (native-inputs (list libtool)) ;; <- only for BC variants + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons* "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:phases + #~(modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. + +Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) + +(define-public racket-minimal-bc-3m + (package + (inherit racket-minimal-bc-cgc) + (name "racket-minimal-bc-3m") + (native-inputs + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (prepend racket-minimal-bc-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Minimal Racket with the BC [3M] runtime system") + (description "The Racket BC (``before Chez'' or ``bytecode'') +implementation was the default before Racket 8.0. It uses a compiler written +in C targeting architecture-independent bytecode, plus a JIT compiler on most +platforms. Racket BC has a different C API and supports a slightly different +set of architectures than the current default runtime system, Racket CS (based +on ``Chez Scheme''). + +This package is the normal implementation of Racket BC with a precise garbage +collector, 3M (``Moving Memory Manager'')."))) + (define-public racket-minimal (package + (inherit racket-minimal-bc-3m) (name "racket-minimal") - (version %racket-version) - (source %racket-origin) (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for CS - zlib - lz4)) + (modify-inputs (package-inputs racket-minimal-bc-cgc) + (prepend zlib lz4) + (delete "libffi"))) (native-inputs - (list chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m)) - (build-system gnu-build-system) + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m))) (arguments - (list - #:configure-flags - #~(cons* "--enable-csonly" - "--enable-libz" - "--enable-lz4" - #$(racket-vm-common-configure-flags)) - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main - ;; distribution. - #:tests? #f - ;; Upstream recommends #:out-of-source?, and it does - ;; help with debugging, but it confuses `install-license-files`. - #:modules '((ice-9 match) - (ice-9 regex) - (guix build gnu-build-system) - (guix build utils)) - #:phases - #~(modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) - (home-page "https://racket-lang.org") + (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) + ((#:phases bc-phases) + #~(modify-phases #$bc-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))))) + ((#:configure-flags _ '()) + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags))))) (synopsis "Racket without bundled packages such as DrRacket") (description "Racket is a general-purpose programming language in the Scheme family, @@ -275,69 +333,11 @@ (define maybe-release-catalog The ``minimal Racket'' distribution includes just enough of Racket for you to use @command{raco pkg} to install more. Bundled packages, such as the DrRacket IDE, are not included.") + (properties `()) ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) -(define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal) - (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (prepend libffi) ;; <- only for BC variants - (delete "zlib" "lz4"))) - (native-inputs - (list libtool - (if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) - ((#:configure-flags _ '()) - #~(cons "--enable-bconly" - #$(racket-vm-common-configure-flags))) - ((#:phases cs-phases) - #~(modify-phases #$cs-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') -implementation was the default before Racket 8.0. It uses a compiler written -in C targeting architecture-independent bytecode, plus a JIT compiler on most -platforms. Racket BC has a different C API and supports a slightly different -set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). - -This package is the normal implementation of Racket BC with a precise garbage -collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:lgpl3+ license:asl2.0 license:expat))))) - -(define-public racket-minimal-bc-cgc - (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs (list libtool)) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:configure-flags _ '()) - #~(cons "--enable-cgcdefault" - #$(racket-vm-common-configure-flags))))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. - -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) - (define-public chez-scheme-for-racket-bootstrap-bootfiles (package (name "chez-scheme-for-racket-bootstrap-bootfiles") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath @ 2022-02-26 14:19 ` Liliana Marie Prikler 2022-02-26 15:16 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 14:19 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > Having the package inheritance chain go in the same direction as the > bootstrapping chain, rather than the opposite, is less confusing. In > some cases, it can also help to avoid unnecessary rebuilds. > > * gnu/packages/racket.scm (racket-minimal-bc-cgc): Change to be the > root > of the package inheritance chain. > [version, source, inputs, native-inputs, build-system, arguments, > home-page, license]: Inline formerly inherited values. > (racket-minimal-bc-3m): Inherit from 'racket-minimal-bc-cgc' rather > than > 'racket-minimal'. > [inputs, native-inputs, arguments, license]: Adjust accordingly. > (racket-minimal): Inherit from 'racket-minimal-bc-3m'. > [inputs, native-inputs, arguments, license]: Adjust accordingly. > [properties]: Override effect of 'hidden-package'. > --- I think this patch might introduce some noise by moving a package to a different location in the file. If possible, we might want to avoid this and relocate afterwards – IIUC positioning within a file should not matter when it comes to the inherit clause. Other than that not much to argue against. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-26 14:19 ` Liliana Marie Prikler @ 2022-02-26 15:16 ` Philip McGrath 2022-02-26 15:19 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 15:16 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 1708 bytes --] Hi, On Saturday, February 26, 2022 9:19:20 AM EST Liliana Marie Prikler wrote: > Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > > Having the package inheritance chain go in the same direction as the > > bootstrapping chain, rather than the opposite, is less confusing. In > > some cases, it can also help to avoid unnecessary rebuilds. > > > > * gnu/packages/racket.scm (racket-minimal-bc-cgc): Change to be the > > root > > of the package inheritance chain. > > [version, source, inputs, native-inputs, build-system, arguments, > > home-page, license]: Inline formerly inherited values. > > (racket-minimal-bc-3m): Inherit from 'racket-minimal-bc-cgc' rather > > than > > 'racket-minimal'. > > [inputs, native-inputs, arguments, license]: Adjust accordingly. > > (racket-minimal): Inherit from 'racket-minimal-bc-3m'. > > [inputs, native-inputs, arguments, license]: Adjust accordingly. > > [properties]: Override effect of 'hidden-package'. > > --- > > I think this patch might introduce some noise by moving a package to a > different location in the file. If possible, we might want to avoid > this and relocate afterwards – IIUC positioning within a file should > not matter when it comes to the inherit clause. > I've tested a few things, and the best result I'm getting is to keep the order as in this patch—the unchanged portion of `arguments` turns out to be longer than the descriptions—but adjust the use of `hidden-package` vs. `properties` to avoid indentation changes. In particular, that helps Git to realize that `racket-minimal-bc-3m` does not move. I'll plan on a v6 with this and other things you've found. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-26 15:16 ` Philip McGrath @ 2022-02-26 15:19 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 15:19 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 10:16 -0500 schrieb Philip McGrath: > I've tested a few things, and the best result I'm getting is to keep > the order as in this patch—the unchanged portion of `arguments` > turns out to be longer than the descriptions—but adjust the use of > `hidden-package` vs. `properties` to avoid indentation changes. In > particular, that helps Git to realize that `racket-minimal-bc-3m` > does not move. > > I'll plan on a v6 with this and other things you've found. Git lacking sexp diffs, our old nemesis! Thanks for investigating. ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 07/22] gnu: racket-minimal: Add "debug" output. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 08/22] gnu: make-installation-layer.rkt: Adjust indentation Philip McGrath ` (15 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (racket-minimal-bc-cgc)[outputs]: Add "debug". (racket-vm-common-configure-flags): Add "--disable-strip". --- gnu/packages/racket.scm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index f5a8091be0..ddbeb68a37 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -151,7 +151,8 @@ (define (racket-vm-common-configure-flags) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - #$(file-append bash-minimal "/bin/sh")))) + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -190,6 +191,7 @@ (define-public racket-minimal-bc-cgc ;; only for BC variants: libffi)) (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 08/22] gnu: make-installation-layer.rkt: Adjust indentation. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 07/22] gnu: racket-minimal: Add "debug" output Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 09/22] gnu: racket-minimal: Separate from the Racket VM Philip McGrath ` (14 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (make-installation-layer.rkt): Wrap 'command-line' in 'define-values' to reduce rightward drift. --- gnu/packages/racket.scm | 164 ++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ddbeb68a37..1670f478ff 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -1358,84 +1358,86 @@ (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) (define extra-foreign-lib-search-dirs '()) - (command-line - #:once-each - [("--extra-foreign-lib-search-dirs") dir-list - "foreign library directories, as a list of strings in `read` syntax" - (set! extra-foreign-lib-search-dirs - (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-update config - 'lib-search-dirs - (lambda (dirs) - ;; add after other layers, but before older - ;; foreign lib search directories - (define-values [rkt old-foreign-dirs] - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - dirs)) - (append rkt - extra-foreign-lib-search-dirs - old-foreign-dirs)))] - [config - (hash-set* config - 'apps-dir - (build-path-string prefix "share/applications") - 'absolute-installation? #t - ;; Let Guix coexist with other installation - ;; methods without clobbering user-specific packages. - ;; This could be set in various places, but doing - ;; it here is convienient, at least until we support - ;; cross-compilation. - 'installation-name - (string-append (version) - "-guix" - (match (system-type 'gc) - ['cgc "-cgc"] - ;; workaroung Guile reader/printer: - ['|3m| "-bc"] - [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (define-values [parent-layer prefix] + (command-line + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) + (values parent-layer prefix))) + (let* ([config + (for/fold + ([config (file->value (build-path parent-layer + config-file-pth))]) + ([spec (in-list + '((lib-dir lib-search-dirs "lib/racket") + (share-dir share-search-dirs "share/racket") + (links-file + links-search-files + "share/racket/links.rktd") + (pkgs-dir pkgs-search-dirs "share/racket/pkgs") + (bin-dir bin-search-dirs "bin") + (man-dir man-search-dirs "share/man") + (doc-dir doc-search-dirs "share/doc/racket") + (include-dir + include-search-dirs + "include/racket")))]) + (match-define (list main-key search-key pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (build-path-string parent-layer pth)) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaroung Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [bin-dir + (hash-ref config 'bin-dir)] + [config + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [new-config-pth + (build-path prefix config-file-pth)]) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 09/22] gnu: racket-minimal: Separate from the Racket VM. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 08/22] gnu: make-installation-layer.rkt: Adjust indentation Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath ` (13 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip For consistency with other Racket distributions, 'racket-minimal' should have the "racket-lib" Racket package installed: see <https://github.com/racket/racket/issues/3851#issuecomment-942368947>. Happily, this gives us a clean boundary between the core Racket VM and compiler, with all of the bootstrapping involved, and building Racket packages and installation layers, which can be handled in a nice, uniform way and eventually turned into a 'racket-build-system'. Building the VM layer as an "in-place" installation should help us use it with other Racket tools. * gnu/packages/racket.scm (racket-vm-common-configure-flags): Add "--enable-origtree". Adapt "--enable-racket=" for "opt/racket-vm/" prefix. (racket-minimal-bc-cgc): Rename to ... (racket-vm-cgc): ... this new variable. [inputs]: Move 'openssl' and 'sqlite' to new 'racket-minimal'. [arguments]<#:strip-directories>: Use "opt/racket-vm/" prefix. <#:phases>: Wrap 'configure', 'patch-shebangs', 'validate-runpath', 'make-dynamic-linker-cache', and 'patch-dot-desktop-files' to use "opt/racket-vm/" prefix. Adapt 'initialize-config.rktd' for removal of 'openssl' and 'sqlite'. [description]: Tweak. (racket-minimal-bc-3m): Rename to ... (racket-vm-bc): ... this new variable. [synopsis, description]: Tweak. (racket-vm-cs): New variable, adapted from the old 'racket-minimal'. (chez-scheme-for-racket-bootstrap-bootfiles)[arguments]<#:phhases>: Adapt to the "opt/racket-vm/" prefix. (racket-minimal): Rewrite like 'racket' using 'racket-vm-cs'. (racket): Inherit from 'racket-minimal'. [inputs]: Add 'racket-vm-cs'. Move "racket-lib" and "base" to 'racket-minimal'. [arguments]<#:make-flags, #:configure-flags>: Override from 'racket-minimal'. (make-installation-layer.rkt): Adapt to support in-place VM build with possible intermediate layer. --- gnu/packages/racket.scm | 598 ++++++++++++++++++++++++++-------------- 1 file changed, 385 insertions(+), 213 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 1670f478ff..a7704f1afe 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -54,7 +54,91 @@ (define-module (gnu packages racket) ;; Commentary: ;; -;; Here's how bootstrapping minimal Racket works: +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: ;; ;; - Racket BC [CGC] can be built with only a C compiler (except for ;; one caveat discussed below). @@ -72,6 +156,10 @@ (define-module (gnu packages racket) ;; ;; So, we build CGC to build 3M to build bootfiles and CS. ;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; ;; One remaining bootstrapping limitation is that Racket's reader, module ;; system, and macro expander are implemented in Racket. For Racket CS, ;; they are compiled to R6RS libraries as discussed above. This note from the @@ -145,14 +233,15 @@ (define (racket-vm-common-configure-flags) '())) ,@(cond ((false-if-exception - (search-input-file %build-inputs "/bin/racket")) + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) => (lambda (racket) (list (string-append "--enable-racket=" racket)))) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" #$(file-append bash-minimal "/bin/sh")) - "--disable-strip")) + "--disable-strip" + "--enable-origtree")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -173,31 +262,25 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal-bc-cgc +(define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. (hidden-package (package - (name "racket-minimal-bc-cgc") + (name "racket-vm-cgc") (version %racket-version) (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants (native-inputs (list libtool)) ;; <- only for BC variants (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main ;; distribution. @@ -208,51 +291,72 @@ (define-public racket-minimal-bc-cgc (ice-9 regex) (guix build gnu-build-system) (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) (home-page "https://racket-lang.org") (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or @@ -262,53 +366,54 @@ (define maybe-release-catalog scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the Racket CS implementation. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-3m +(define-public racket-vm-bc (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") + (inherit racket-vm-cgc) + (name "racket-vm-bc") (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + (substitute-keyword-arguments (package-arguments racket-vm-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") + (synopsis "Racket BC [3M] implementation") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'')."))) -(define-public racket-minimal +(define-public racket-vm-cs (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal") + (inherit racket-vm-bc) + (name "racket-vm-cs") (inputs - (modify-inputs (package-inputs racket-minimal-bc-cgc) + (modify-inputs (package-inputs racket-vm-cgc) (prepend zlib lz4) (delete "libffi"))) (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m))) + racket-vm-bc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:phases bc-phases) - #~(modify-phases #$bc-phases + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" @@ -325,17 +430,14 @@ (define-public racket-minimal "--enable-libz" "--enable-lz4" #$(racket-vm-common-configure-flags))))) - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") - (properties `()) +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) @@ -350,7 +452,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source %racket-origin) (inputs `()) - (native-inputs (list racket-minimal-bc-3m)) + (native-inputs (list racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -368,7 +470,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) - "/bin/racket") + "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, @@ -447,10 +549,116 @@ (define (extract-package-source* source-groups) specs))) source-groups)) +(define-public racket-minimal + (package + (name "racket-minimal") + (version %racket-version) + (source #f) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs + (cons* openssl + sqlite + racket-vm-cs ;; TODO (racket-vm-for-system) + (extract-package-source* + `((,%racket-origin + ("base" "pkgs/base") + ("racket-lib" "pkgs/racket-lib")))))) + (build-system gnu-build-system) + (arguments + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `make-installation-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install` + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format + #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$make-installation-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. + +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + (define-public racket (package + (inherit racket-minimal) (name "racket") - (version %racket-version) (source #f) (inputs (cons* @@ -469,6 +677,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer + racket-vm-cs ;; TODO (racket-vm-for-system) (extract-package-source* `((,(origin (method git-fetch) @@ -491,8 +700,6 @@ (define-public racket (git-file-name "racket-algol60" %racket-version))) ("algol60" ".")) (,%racket-origin - ("base" "pkgs/base") ;; FIXME belongs in racket-minimal - ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal ("at-exp-lib" "pkgs/at-exp-lib") ("compiler" "pkgs/compiler") ("compiler-lib" "pkgs/compiler-lib") @@ -1238,93 +1445,40 @@ (define-public racket "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3")) (file-name (git-file-name "racket-xrepl" %racket-version))) "xrepl" "xrepl-doc" "xrepl-lib"))))) - (build-system gnu-build-system) (arguments - ;; We're using #:configure-flags to pass flags for - ;; `make-installation-layer.rkt` and #:make-flags to pass arguments for - ;; `raco pkg install`. - (list - #:configure-flags - #~`("--extra-foreign-lib-search-dirs" - ,(format #f "~s" - '(#$@(map (lambda (name) - (cond - ((this-package-input name) - => (cut file-append <> "/lib")) - (else - (raise-exception - (make-exception - (make-assertion-failure) - (make-exception-with-message - "missing input to the 'racket' package") - (make-exception-with-irritants - (list name))))))) - '("cairo" - "fontconfig-minimal" ;; aka fontconfig - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg-turbo" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))))) - #:make-flags #~`("main-distribution") - #:tests? #f ;; packaged separately - #:modules '((guix build gnu-build-system) - (guix build utils) - (guix build union) - (ice-9 match)) - #:imported-modules `((guix build union) - ,@%gnu-build-system-modules) - #:phases - #~(modify-phases %standard-phases - (delete 'unpack) - (replace 'configure - (lambda* (#:key inputs configure-flags #:allow-other-keys) - (let* ((racket (search-input-file inputs "bin/racket"))) - (apply invoke - racket - #$make-installation-layer.rkt - `(,@configure-flags - ,(dirname (dirname racket)) - ,#$output)) - (invoke racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" "setup" - "--no-user")))) - (replace 'build - (lambda* (#:key inputs #:allow-other-keys) - ;; We use "share/racket/pkgs" for sources to distinguish them - ;; from the "lib/racket/pkgs" of a potential parent layer. - (union-build (string-append #$output "/lib/racket/pkgs") - (search-path-as-list '("share/racket/pkgs") - (map cdr inputs)) - #:create-all-directories? #t))) - (replace 'install - (lambda* (#:key inputs make-flags #:allow-other-keys) - (let ((racket (search-input-file inputs "/bin/racket"))) - (unless (null? make-flags) - (invoke racket - "-l-" - "pkg/dirs-catalog" - "--link" - "local-catalog" - (string-append #$output "/lib/racket/pkgs")) - (apply invoke - racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" - "pkg" "install" - "--installation" - "--auto" - "--catalog" "local-catalog" - make-flags)))))))) - (home-page "https://racket-lang.org") + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -1334,10 +1488,7 @@ (define-public racket The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) (define make-installation-layer.rkt (scheme-file @@ -1350,41 +1501,53 @@ (define make-installation-layer.rkt racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define tethered? #f) + (define parent #f) (define extra-foreign-lib-search-dirs '()) - (define-values [parent-layer prefix] + (define-values [vm-dir prefix] (command-line #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] [("--extra-foreign-lib-search-dirs") dir-list "foreign library directories, as a list of strings in `read` syntax" (set! extra-foreign-lib-search-dirs (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (values parent-layer prefix))) + #:args (vm-dir prefix) + (values vm-dir prefix))) (let* ([config (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) (hash-set* config main-key @@ -1393,7 +1556,10 @@ (define-values [parent-layer prefix] (list* #f (hash-ref config main-key - (build-path-string parent-layer pth)) + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) (filter values (hash-ref config search-key null)))))] [config (hash-update config @@ -1427,15 +1593,21 @@ (define-values [rkt old-foreign-dirs] ;; workaroung Guile reader/printer: ['|3m| "-bc"] [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) (make-parent-directory* new-config-pth) (call-with-output-file* new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez). 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 09/22] gnu: racket-minimal: Separate from the Racket VM Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 14:31 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 11/22] gnu: chez: Add utilities for Chez machine types Philip McGrath ` (12 subsequent siblings) 22 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (chez-scheme-for-racket-bootstrap-bootfiles): Move to ... * gnu/packages/chez.scm (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable. [source]: Avoid problematic cycle with "racket.scm". [arguments]<#:phases>: Likewise. --- gnu/packages/chez.scm | 62 +++++++++++++++++++++++++++++++++++++++++ gnu/packages/racket.scm | 52 ---------------------------------- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..046bb3dcdc 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -31,12 +31,14 @@ (define-module (gnu packages chez) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) #:use-module (gnu packages linux) #:use-module (gnu packages netpbm) + #:use-module (gnu packages racket) #:use-module (gnu packages tex) #:use-module (gnu packages compression) #:use-module (gnu packages image) @@ -260,6 +262,66 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs `()) + (native-inputs (list racket-vm-bc)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(let ((unpack (assoc-ref %standard-phases 'unpack))) + (modify-phases %standard-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + (copy-recursively + #$nanopass + "nanopass" + #:keep-mtime? #t))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme.") + (license (list asl2.0)))) + (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a7704f1afe..ba958b6101 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -442,58 +442,6 @@ (define-public racket-vm-cs ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) -(define-public chez-scheme-for-racket-bootstrap-bootfiles - (package - (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (source %racket-origin) - (inputs `()) - (native-inputs (list racket-vm-bc)) - (build-system copy-build-system) - ;; TODO: cross compilation - (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(modify-phases %standard-phases - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$(make-unpack-nanopass+stex))) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt")))))) - (home-page "https://github.com/racket/ChezScheme") - ;; ^ This is downstream of https://github.com/racket/racket, - ;; but it's designed to be a friendly landing place for people - ;; who want a ChezScheme-shaped repositroy. - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list license:asl2.0)))) - (define (extract-package-source origin spec) "Extract the source for a Racket package specified by SPEC from ORIGIN into a new file-like object. In the resulting file-like object, the package source -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez). 2022-02-26 13:02 ` [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath @ 2022-02-26 14:31 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 14:31 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > ´ gnu/packages/chez.scm | 62 > +++++++++++++++++++++++++++++++++++++++++ > gnu/packages/racket.scm | 52 ---------------------------------- > 2 files changed, 62 insertions(+), 52 deletions(-) You were the chosen one Philip! The prophecy said you would reduce the code size for racket chez, not add more to it! Prequel memes aside, LGTM on the basis that we will probably be reusing some bits in the later commits and also there's chez-scheme-for-system to think about. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 11/22] gnu: chez: Add utilities for Chez machine types. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 12/22] gnu: racket: Add 'racket-vm-for-system' Philip McGrath ` (11 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/chez.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. (chez-scheme-for-racket-bootstrap-bootfiles)[supported-systems]: Compute based on 'nix-system->chez-machine'. --- gnu/packages/chez.scm | 127 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 046bb3dcdc..603fc4201e 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -44,7 +44,119 @@ (define-module (gnu packages chez) #:use-module (gnu packages image) #:use-module (gnu packages xorg) #:use-module (ice-9 match) - #:use-module (srfi srfi-1)) + #:use-module (srfi srfi-1) + #:export (nix-system->chez-machine + chez-machine->nonthreaded + chez-machine->threaded)) + +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; (define nanopass (let ((version "1.9.2")) @@ -251,8 +363,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description @@ -300,6 +415,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people @@ -322,6 +439,10 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Chez Scheme.") (license (list asl2.0)))) +;; +;; Packages: +;; + (define-public chez-srfi (package (name "chez-srfi") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 12/22] gnu: racket: Add 'racket-vm-for-system'. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (10 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 11/22] gnu: chez: Add utilities for Chez machine types Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (10 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (racket-vm-for-system): New procedure. (racket-minimal, racket)[inputs]: Use it. --- gnu/packages/racket.scm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ba958b6101..93e5eea158 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -187,6 +187,14 @@ (define-module (gnu packages racket) ;; ;; Code: +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define %racket-version "8.4") ;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit @@ -508,7 +516,7 @@ (define-public racket-minimal (inputs (cons* openssl sqlite - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (extract-package-source* `((,%racket-origin ("base" "pkgs/base") @@ -625,7 +633,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (extract-package-source* `((,(origin (method git-fetch) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (11 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 12/22] gnu: racket: Add 'racket-vm-for-system' Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 14:34 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 14/22] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (9 subsequent siblings) 22 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove input labels and use G-expressions. --- gnu/packages/chez.scm | 382 +++++++++++++++++++++--------------------- 1 file changed, 194 insertions(+), 188 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 603fc4201e..0a84a07247 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -233,7 +233,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments `(#:modules @@ -443,6 +443,27 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; Packages: ;; +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -460,13 +481,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -491,42 +510,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -550,95 +575,74 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/chez-scheme/arcfide"))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/chez-scheme/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -659,10 +663,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -690,10 +695,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -720,17 +726,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -760,10 +767,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -792,46 +800,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) - (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) - (with-directory-excursion (dirname mk-file) - (apply invoke "make" "build" make-flags))))) - (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) + (add-after 'absolute-path-in-scm-files 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) + (with-directory-excursion (dirname mk-file) + (apply invoke "make" "build" make-flags))))) + (add-after 'build 'clean-up + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-26 14:34 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 14:34 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > There does not seem to be any widely accepted standard path to use > for > "CHEZSCHEMELIBDIRS". Using a path without a version number in it > avoids > having to compute the actual path everywhere, which would be > especially > unpleasant when support is added for the Racket variant of Chez > Scheme, > which always has a different version number than upstream. > > * gnu/packages/chez.scm (chez-scheme)[native-search-paths]: Change to > use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for > "CHEZSCHEMELIBDIRS". > (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, > chez-fmt, chez-mit, chez-scmutils): Update accordingly. Also, remove > input labels and use G-expressions. I do think we ought to divorce the functional changes from the style changes, but I'm willing to let this one slide. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 14/22] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (12 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 15/22] gnu: chez-scheme: Use new package style Philip McGrath ` (8 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 0a84a07247..43332c06ad 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -211,9 +211,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -266,14 +264,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 15/22] gnu: chez-scheme: Use new package style. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (13 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 14/22] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 16/22] gnu: Add stex Philip McGrath ` (7 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove labels. [native-inputs]: Likewise. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass): Make public as a temporary workaround for Racket. * gnu/packages/racket.scm (make-unpack-nanopass+stex): Update accordingly. --- gnu/packages/chez.scm | 286 +++++++++++++++++++--------------------- gnu/packages/racket.scm | 5 +- 2 files changed, 135 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 43332c06ad..a130f2f41a 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -158,7 +158,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -185,86 +185,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files (list (string-append "lib/chez-scheme")))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -272,90 +266,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 93e5eea158..3ba1438014 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -257,10 +257,7 @@ (define (make-unpack-nanopass+stex) ;; Thunked to avoid evaliating 'chez-scheme' too early. #~(begin (copy-recursively - #$(match (assoc-ref (package-native-inputs chez-scheme) - "nanopass") - ((src) - src)) + #$nanopass "nanopass" #:keep-mtime? #t) (mkdir-p "stex") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 16/22] gnu: Add stex. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (14 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 15/22] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 17/22] gnu: Add chez-nanopass Philip McGrath ` (6 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/chez.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap' (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. --- gnu/packages/chez.scm | 217 ++++++++++++++++++++++++++++++------------ 1 file changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index a130f2f41a..99a250154f 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -33,6 +33,7 @@ (define-module (gnu packages chez) #:use-module (guix gexp) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) + #:use-module (guix build-system copy) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) @@ -158,30 +159,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -218,15 +195,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -249,9 +218,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -287,32 +258,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -320,7 +268,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -420,7 +370,150 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (license (list asl2.0)))) ;; -;; Packages: +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +;; +;; Other Chez packages: ;; ;; Help function for Chez Scheme to add the current path to -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 17/22] gnu: Add chez-nanopass. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (15 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 16/22] gnu: Add stex Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 18/22] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (5 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/chez.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-nanopass): New variable. (unpack-nanopass+stex): New variable using 'chez-nanopass-bootstrap'. (chez-scheme-for-racket-bootstrap-bootfiles, chez-scheme)[native-inputs]: Add 'chez-nanopass-bootstrap'. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. * gnu/packages/racket.scm (racket-vm-cs): Likewise. (make-unpack-nanopass+stex): Remove it. --- gnu/packages/chez.scm | 122 +++++++++++++++++++++++++++++++--------- gnu/packages/racket.scm | 19 +------ 2 files changed, 98 insertions(+), 43 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 99a250154f..ba555e6830 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -48,7 +48,8 @@ (define-module (gnu packages chez) #:use-module (srfi srfi-1) #:export (nix-system->chez-machine chez-machine->nonthreaded - chez-machine->threaded)) + chez-machine->threaded + unpack-nanopass+stex)) (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string @@ -159,6 +160,20 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; + +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + (define-public chez-scheme (package (name "chez-scheme") @@ -176,6 +191,9 @@ (define-public chez-scheme (file-name (git-file-name name version)) (snippet #~(begin (use-modules (guix build utils)) + ;; TODO: consider putting this in a (guix ...) or + ;; (guix build ...) module so it can be shared + ;; with the Racket origin without cyclic issues. (for-each (lambda (dir) (when (directory-exists? dir) (delete-file-recursively dir))) @@ -193,9 +211,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -215,14 +231,7 @@ (define-public chez-scheme #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + #$unpack-nanopass+stex)) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -317,7 +326,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm (inputs `()) - (native-inputs (list racket-vm-bc)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -336,10 +345,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (chdir "racket/src/ChezScheme"))) (add-after 'chdir 'unpack-nanopass+stex (lambda args - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t))) + #$unpack-nanopass+stex)) (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) @@ -502,15 +508,79 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) ;; ;; Other Chez packages: diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 3ba1438014..9ed57e6154 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -251,22 +251,6 @@ (define (racket-vm-common-configure-flags) "--disable-strip" "--enable-origtree")) -(define (make-unpack-nanopass+stex) - ;; Adapted from chez-scheme. - ;; TODO: Refactor enough to share this directly. - ;; Thunked to avoid evaliating 'chez-scheme' too early. - #~(begin - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) - - (define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. @@ -414,6 +398,7 @@ (define-public racket-vm-cs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles + chez-nanopass-bootstrap racket-vm-bc))) (arguments (substitute-keyword-arguments (package-arguments racket-vm-cgc) @@ -422,7 +407,7 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) + #$unpack-nanopass+stex))) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (with-directory-excursion "racket/src/ChezScheme" -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 18/22] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (16 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 17/22] gnu: Add chez-nanopass Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 19/22] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (4 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip This makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. (chez-scheme-for-racket-bootstrap-bootfiles): Inherit from 'chez-scheme-bootstrap-bootfiles'. [arguments]: Adapt accordingly. --- gnu/packages/chez.scm | 98 +++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index ba555e6830..4818e59837 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -46,6 +46,7 @@ (define-module (gnu packages chez) #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded @@ -211,7 +212,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -232,6 +235,14 @@ (define-public chez-scheme (add-after 'unpack 'unpack-nanopass+stex (lambda args #$unpack-nanopass+stex)) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -316,8 +327,46 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + (define-public chez-scheme-for-racket-bootstrap-bootfiles (package + (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") (version "9.5.7.3") ;; The version should match `(scheme-fork-version-number)`. @@ -325,32 +374,30 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; It will always be different than the upstream version! ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm - (inputs `()) (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) - (build-system copy-build-system) ;; TODO: cross compilation (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(let ((unpack (assoc-ref %standard-phases 'unpack))) - (modify-phases %standard-phases - (replace 'unpack - (lambda args - (unpack #:source #$(or (package-source this-package) - (package-source racket-vm-bc))))) - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$unpack-nanopass+stex)) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt"))))))) + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt")))))))) (supported-systems (filter nix-system->chez-machine %supported-systems)) (home-page "https://github.com/racket/ChezScheme") @@ -372,8 +419,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0)))) +Chez Scheme."))) ;; ;; Chez's bootstrap dependencies: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 19/22] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (17 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 18/22] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 20/22] gnu: Add chez-scheme-for-racket Philip McGrath ` (3 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 4818e59837..f258732baf 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -949,7 +949,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 20/22] gnu: Add chez-scheme-for-racket. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (18 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 19/22] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 21/22] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath ` (2 subsequent siblings) 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez.scm (chez-scheme-for-racket): New variable. (chez-scheme-for-racket-bootstrap-bootfiles)[version, supported-systems]: Derive from 'chez-scheme-for-racket'. * gnu/packages/racket.scm (%racket-version): Update comment. --- gnu/packages/chez.scm | 97 ++++++++++++++++++++++++++++++++++++++--- gnu/packages/racket.scm | 3 +- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index f258732baf..a6b5952819 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -52,6 +52,21 @@ (define-module (gnu packages chez) chez-machine->threaded unpack-nanopass+stex)) +;; Commentary: +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Code: + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -327,6 +342,78 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme")))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license asl2.0))) + +;; +;; Bootfiles: +;; + (define-public chez-scheme-bootstrap-bootfiles (package (inherit chez-scheme) @@ -368,11 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (package (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. + (version (package-version chez-scheme-for-racket)) (source #f) ; avoid problematic cycle with racket.scm (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) ;; TODO: cross compilation @@ -398,8 +481,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))))) - (supported-systems (filter nix-system->chez-machine - %supported-systems)) + (supported-systems + (package-supported-systems chez-scheme-for-racket)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 9ed57e6154..3f73d6bc83 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -195,8 +195,7 @@ (define* (racket-vm-for-system #:optional racket-vm-cs racket-vm-bc)) -(define %racket-version "8.4") -;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! +(define %racket-version "8.4") ; Remember to update chez-scheme-for-racket! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 21/22] gnu: chez: Add 'chez-scheme-for-system'. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (19 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 20/22] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 22/22] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 2022-02-26 15:08 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/chez.scm (chez-scheme-for-system): New procedure. (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Use 'chez-scheme-for-system'. * gnu/packages/loko.scm (loko-scheme): Likewise. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise --- gnu/packages/chez.scm | 33 ++++++++++++++++++++++++--------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index a6b5952819..c7505a14bd 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -47,7 +47,8 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) - #:export (nix-system->chez-machine + #:export (chez-scheme-for-system + nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded unpack-nanopass+stex)) @@ -67,6 +68,20 @@ (define-module (gnu packages chez) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (or + ;; full support upstream + (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)) + ;; no support anywhere + (not (nix-system->chez-machine system))) + chez-scheme + chez-scheme-for-racket)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -751,7 +766,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -782,7 +797,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -847,7 +862,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -933,7 +948,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -965,7 +980,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -996,7 +1011,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -1059,7 +1074,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -1090,7 +1105,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index ef98088100..df53df61c7 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..449c62f1f0 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 22/22] gnu: racket-vm-cs: Build with "--enable-scheme". 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (20 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 21/22] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-26 13:02 ` Philip McGrath 2022-02-26 15:08 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler 22 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 13:02 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom, philip * gnu/packages/racket.scm (racket-vm-cs)[native-inputs]: Remove 'chez-scheme-for-racket-bootstrap-bootfiles'. Add 'chez-scheme-for-racket'. [arguments]<#:phases>: Delete 'unpack-bootfiles'. <#:configure-flags>: Add "--enable-scheme". --- gnu/packages/racket.scm | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 3f73d6bc83..f70b027160 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -396,7 +396,7 @@ (define-public racket-vm-cs (native-inputs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") - (prepend chez-scheme-for-racket-bootstrap-bootfiles + (prepend chez-scheme-for-racket chez-nanopass-bootstrap racket-vm-bc))) (arguments @@ -406,18 +406,15 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$unpack-nanopass+stex))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))))) + #$unpack-nanopass+stex))))) ((#:configure-flags _ '()) #~(cons* "--enable-csonly" "--enable-libz" "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") #$(racket-vm-common-configure-flags))))) (synopsis "Racket CS implementation") (description "The Racket CS implementation, which uses ``Chez Scheme'' as -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (21 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 22/22] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath @ 2022-02-26 15:08 ` Liliana Marie Prikler 2022-02-26 15:36 ` Philip McGrath 22 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 15:08 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > Hi, > > I've been ruminating for a while on Liliana's comment > from <https://issues.guix.gnu.org/53878#118>: > > On Wednesday, February 23, 2022 3:31:34 PM EST Liliana Marie Prikler > wrote: > > [...] there are some things that still > > don't feel right for me – for instance the fact, that seemingly > > unrelated modules now have to pull in racket bootstrap sounds like > > a recipe for trouble. The final patch in the series also still > > does too much for me to wrap my head around, which makes it > > difficult to audit. > > > > Therefore, one question I have w.r.t. updating Racket is whether we > > could theoretically bump the version while keeping the old > > bootstrap, and then adjust the bootstrap by adding all the packages > > you've made. It does seem to be an all or nothing deal when doing > > the bootstrap first, but that need not necessarily hold for > > bootstrap second. > > > > Also, accepting for a moment that we might have to move chez-scheme > > and other important things into chez-scheme-and-racket-bootstrap > > (even though I'm not really content with it), I still wonder if we > > could introduce chez-scheme-for-system first (defined as simply > > chez-scheme initially) and adjust the callers, then move chez- > > scheme while keeping the function in chez.scm and finally do the > > magic with making it either chez or racket. > > > > It struck me that the core of the dependency cycle (at least, from > one perspective) is that 'chez-scheme-for-racket' wants to 'inherit' > from 'chez-scheme' but use '%racket-origin' for its 'source', and > neither of those are thunked fields. I did realize that too, but perhaps I failed to mention that or didn't get the point across before this, so pardon me for the extra work you had to put in that I could have helped avoid. > I realized that, if we just pass the origin some other way than as > the 'source' field, we can avoid adding the > "chez-and-racket-bootstrap.scm" file > altogether: patch v5 10/22 does the core of that. I did miss that nugget when I skimmed it first; is there a reason to prefer overloading unpack and redirecting it to (package-source racket- vm-bc) over doing the same, but using simply #$%racket-origin? > I also managed to split up the update to Racket 8.4 (patch v4 15/15) > into a number of smaller steps (or, more precisely, rewrite it now > that I knew what the end result would be). I now have the 'racket- > minimal*' packages gradually evolve into the corresponding 'racket- > vm-*' packages (rather than adding the 'racket-vm-*' stack in > parallel), then split the new 'racket-minimal' package > out of 'racket'. Hopefully this might be somewhat easier to review. > The downside is there are now 22 patches, rather than 15. In general, smaller patches = more better. I really like this series so far, there's only some cosmetic nitpicks, although for the record I do have to say that I skipped over many things that felt familiar from earlier series. BTW for the record, if you're dropping one of my mails from the CCs, please make sure to include the gmail account rather than my institute mail. This one is technically supposed to be for work and I'm using a rather loose interpretation of "ensuring that software is up-to-date" as part of my work when I do comment on Guix issues from it. I'll now attempt to build racket with this patch and hopefully encounter no error as I do. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-26 15:08 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler @ 2022-02-26 15:36 ` Philip McGrath 2022-02-26 16:14 ` Liliana Marie Prikler 0 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-26 15:36 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Liliana Marie Prikler, raingloom, Attila Lendvai, Malte Gerdes [-- Attachment #1: Type: text/plain, Size: 2847 bytes --] Hi, On Saturday, February 26, 2022 10:08:30 AM EST Liliana Marie Prikler wrote: > Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > > I realized that, if we just pass the origin some other way than as > > the 'source' field, we can avoid adding the > > "chez-and-racket-bootstrap.scm" file > > altogether: patch v5 10/22 does the core of that. > > I did miss that nugget when I skimmed it first; is there a reason to > prefer overloading unpack and redirecting it to (package-source racket- > vm-bc) over doing the same, but using simply #$%racket-origin? > I like this: > > + (replace 'unpack > > + (lambda args > > + (unpack #:source #$(or (package-source this-package) > > + (package-source racket-vm-bc))))) rather than: (unpack #:source #$(package-source racket-vm-bc)) to make it easier for a user to provide an alternate source. My concern with: (unpack #:source #$(or (package-source this-package) %racket-origin)) is less strong, but if `(gnu packages racket)` exports `%racket-origin`, it seems like it would be very tempting to put it in a `source` field, but of course that would cause problems. My hope was that having to write `(package-source racket-vm-bc)` might prompt a little more thought. > > I also managed to split up the update to Racket 8.4 (patch v4 15/15) > > into a number of smaller steps (or, more precisely, rewrite it now > > that I knew what the end result would be). I now have the 'racket- > > minimal*' packages gradually evolve into the corresponding 'racket- > > vm-*' packages (rather than adding the 'racket-vm-*' stack in > > parallel), then split the new 'racket-minimal' package > > out of 'racket'. Hopefully this might be somewhat easier to review. > > The downside is there are now 22 patches, rather than 15. > > In general, smaller patches = more better. I really like this series > so far, there's only some cosmetic nitpicks, although for the record I > do have to say that I skipped over many things that felt familiar from > earlier series. Thanks! > > BTW for the record, if you're dropping one of my mails from the CCs, > please make sure to include the gmail account rather than my institute > mail. This one is technically supposed to be for work and I'm using a > rather loose interpretation of "ensuring that software is up-to-date" > as part of my work when I do comment on Guix issues from it. Will do, sorry! (I've been experimenting with MUAs recently and not getting everything right—you may have noticed I sent mail earlier from an address I wasn't intending to use.) > > I'll now attempt to build racket with this patch and hopefully > encounter no error as I do. > > Cheers -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-26 15:36 ` Philip McGrath @ 2022-02-26 16:14 ` Liliana Marie Prikler 2022-02-26 17:31 ` Philip McGrath 0 siblings, 1 reply; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-26 16:14 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom Hi, Am Samstag, dem 26.02.2022 um 10:36 -0500 schrieb Philip McGrath: > Hi, > > On Saturday, February 26, 2022 10:08:30 AM EST Liliana Marie Prikler > wrote: > > Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > > > I realized that, if we just pass the origin some other way than > > > as the 'source' field, we can avoid adding the > > > "chez-and-racket-bootstrap.scm" file > > > altogether: patch v5 10/22 does the core of that. > > > > I did miss that nugget when I skimmed it first; is there a reason > > to prefer overloading unpack and redirecting it to (package-source > > racket-vm-bc) over doing the same, but using simply #$%racket- > > origin? > > > > I like this: > > > > + (replace 'unpack > > > + (lambda args > > > + (unpack #:source #$(or (package-source this- > > > package) > > > + (package-source racket- > > > vm-bc))))) > > rather than: > > (unpack #:source #$(package-source racket-vm-bc)) > > to make it easier for a user to provide an alternate source. Hmm, to be fair this would probably respect --with-source, which I was missing, but I'm not sure how deep into the bootstrap we could inject this. Sadly, we can't make chez-scheme-for-racket itself a transformation. > My concern with: > > (unpack #:source #$(or (package-source this-package) %racket- > origin)) > > is less strong, but if `(gnu packages racket)` exports `%racket- > origin`, it > seems like it would be very tempting to put it in a `source` field, > but of course that would cause problems. My hope was that having to > write `(package-source racket-vm-bc)` might prompt a little more > thought. Hmm. And what if we go my earlier route of defining this as a procedure in chez and instantiating it inside racket.scm? We should not get a cycle triggered by chez-scheme-for-system if we do, but we might get one if we attempt to bind it to a variable in racket.scm. That aside, there is also the possibility of using a gexp promise as source, as is done for example in the case of linux-libre. If we wrap the chez side in a promise, that ought to resolve the cycle as well. > > > > BTW for the record, if you're dropping one of my mails from the > > CCs, please make sure to include the gmail account rather than my > > institute mail. This one is technically supposed to be for work > > and I'm using a rather loose interpretation of "ensuring that > > software is up-to-date" as part of my work when I do comment on > > Guix issues from it. > > Will do, sorry! (I've been experimenting with MUAs recently and not > getting everything right—you may have noticed I sent mail earlier > from an address I wasn't intending to use.) I haven't noticed, but thanks for pointing this out. If a commit from the wrong address does make it into our git history, please do point that out; I'll be happy to adjust the mailmap for you. > Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-26 16:14 ` Liliana Marie Prikler @ 2022-02-26 17:31 ` Philip McGrath 0 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-26 17:31 UTC (permalink / raw) To: 53878, zimoun, Liliana Marie Prikler, Liliana Marie Prikler Cc: Ludovic Courtès, Maxime Devos, Attila Lendvai, Malte Gerdes, raingloom [-- Attachment #1: Type: text/plain, Size: 3830 bytes --] Hi, On Saturday, February 26, 2022 11:14:38 AM EST Liliana Marie Prikler wrote: > Hi, > > Am Samstag, dem 26.02.2022 um 10:36 -0500 schrieb Philip McGrath: > > Hi, > > > > On Saturday, February 26, 2022 10:08:30 AM EST Liliana Marie Prikler > > > > wrote: > > > Am Samstag, dem 26.02.2022 um 08:02 -0500 schrieb Philip McGrath: > > > > I realized that, if we just pass the origin some other way than > > > > as the 'source' field, we can avoid adding the > > > > "chez-and-racket-bootstrap.scm" file > > > > altogether: patch v5 10/22 does the core of that. > > > > > > I did miss that nugget when I skimmed it first; is there a reason > > > to prefer overloading unpack and redirecting it to (package-source > > > racket-vm-bc) over doing the same, but using simply #$%racket- > > > origin? > > > > I like this: > > > > + (replace 'unpack > > > > + (lambda args > > > > + (unpack #:source #$(or (package-source this- > > > > package) > > > > + (package-source racket- > > > > vm-bc))))) > > > > rather than: > > > > (unpack #:source #$(package-source racket-vm-bc)) > > > > to make it easier for a user to provide an alternate source. > > Hmm, to be fair this would probably respect --with-source, which I was > missing, but I'm not sure how deep into the bootstrap we could inject > this. Sadly, we can't make chez-scheme-for-racket itself a > transformation. > > > My concern with: > > > > (unpack #:source #$(or (package-source this-package) %racket- > > origin)) > > > > is less strong, but if `(gnu packages racket)` exports `%racket- > > origin`, it > > seems like it would be very tempting to put it in a `source` field, > > but of course that would cause problems. My hope was that having to > > write `(package-source racket-vm-bc)` might prompt a little more > > thought. > > Hmm. And what if we go my earlier route of defining this as a > procedure in chez and instantiating it inside racket.scm? We should > not get a cycle triggered by chez-scheme-for-system if we do, but we > might get one if we attempt to bind it to a variable in racket.scm. > > That aside, there is also the possibility of using a gexp promise as > source, as is done for example in the case of linux-libre. If we wrap > the chez side in a promise, that ought to resolve the cycle as well. > Interesting ... I'll have to take a look at that. In the medium term, for Racket packages, I think the 'racket-build-system' ought to provide some support for using a different Racket. For Chez Scheme packages it's probably less complicated. (At least, I've had no problems with the things I've tried.) For now, mostly I thought it would be very surprising if `unpack` silently ignored the package's `source` and unpacked something else, instead. > > > BTW for the record, if you're dropping one of my mails from the > > > CCs, please make sure to include the gmail account rather than my > > > institute mail. This one is technically supposed to be for work > > > and I'm using a rather loose interpretation of "ensuring that > > > software is up-to-date" as part of my work when I do comment on > > > Guix issues from it. > > > > Will do, sorry! (I've been experimenting with MUAs recently and not > > getting everything right—you may have noticed I sent mail earlier > > from an address I wasn't intending to use.) > > I haven't noticed, but thanks for pointing this out. If a commit from > the wrong address does make it into our git history, please do point > that out; I'll be happy to adjust the mailmap for you. > Thankfully git and git-send-email have been fine; only a couple prose messages came from the wrong address. -Philip [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 00/24] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (15 preceding siblings ...) 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath ` (23 more replies) 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 17 siblings, 24 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Hi, Here is v6, reflecting (I hope) Liliana's suggestions. Compared to v5: - The first two patches are the same. - Patch 03 uses "configure-layer.rkt" rather than "make-installation-layer.rkt", fixes a typo, and uses 'racket-packages-origin' and 'simple-racket-origin' rather than 'extract-package-source{,*}'. - Patch 04 has a typo fix. - Patch 05 is the same. - Patch v6 06/24 is like v5 06/22, but with a smaller diff, because it avoids changing indentation. - Patch v6 07/24 makes the indentation changes that were part of v5 06/22. - Patches 08/24 through 13/24 are like v5 07/22 through 12/22. - Patch v6 14/24 includes only the style changes from v5 13/22. - Patch v6 15/24 is the substantive part of v5 13/22. - Patches 16/24 through 24/24 correspond to v5 14/22 through 22/22. Thanks! -Philip Philip McGrath (24): gnu: Use license prefix in (gnu packages racket). gnu: racket: Update to 8.4. gnu: racket: Use Git origins for Racket packages. gnu: racket-minimal: Use new package style. gnu: racket-minimal: Don't configure non-existant catalogs. gnu: racket-minimal: Change inheritance to follow bootstrapping. gnu: racket-minimal: Adjust indentation. gnu: racket-minimal: Add "debug" output. gnu: configure-layer.rkt: Adjust indentation. gnu: racket-minimal: Separate from the Racket VM. gnu: racket: Move Chez bootfiles to (gnu packages chez). gnu: chez: Add utilities for Chez machine types. gnu: racket: Add 'racket-vm-for-system'. gnu: chez-scheme: Use new style for Chez packages. gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: chez-mit: Support chez-scheme-for-racket. gnu: Add chez-scheme-for-racket. gnu: chez: Add 'chez-scheme-for-system'. gnu: racket-vm-cs: Build with "--enable-scheme". gnu/local.mk | 4 +- gnu/packages/chez.scm | 1264 ++++++++++----- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- .../racket-enable-scheme-backport.patch | 465 ++++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1433 +++++++++++------ 7 files changed, 2342 insertions(+), 854 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 01/24] gnu: Use license prefix in (gnu packages racket). 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 02/24] gnu: racket: Update to 8.4 Philip McGrath ` (22 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal, racket-minimal-bc-3m, racket-bootstrap-chez-bootfiles): Use license prefix. --- gnu/packages/racket.scm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..ec9e836a4c 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -47,7 +45,8 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) #:prefix license:)) ;; Commentary: ;; @@ -254,7 +253,7 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) + (license (list license:asl2.0 license:expat)))) (define-public racket-minimal-bc-3m @@ -295,7 +294,7 @@ (define-public racket-minimal-bc-3m collector, 3M (``Moving Memory Manager'').") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) + (license (list license:lgpl3+ license:asl2.0 license:expat))))) (define-public racket-minimal-bc-cgc @@ -372,7 +371,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list asl2.0))))) + (license (list license:asl2.0))))) (define %installer-mirrors -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 02/24] gnu: racket: Update to 8.4. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath ` (21 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-enable-scheme-backport.patch, gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New patches. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/racket.scm (%racket-version): New variable. (%racket-commit): New variable. (%racket-origin): New variable. [patches]: Add "racket-enable-scheme-backport.patch". (racket-minimal): Update to 8.4. [version]: Use '%racket-version'. [source]: Use '%racket-origin'. [inputs]: Add 'ncurses'. Remove 'zlib:static' and 'lz4:static'. (racket-minimal-bc-3m)[inputs]: Adjust accordingly. (racket-bootstrap-chez-bootfiles)[version]: Use Chez Scheme's '(scheme-fork-version-number)'. (racket)[version]: Use '%racket-version'. [native-inputs]: Use '%racket-origin'. [source]: Update to 8.4. <patches>: Use "racket-gui-tethered-launcher-backport.patch". <snippet>: Remove "srfi-doc-nonfree". --- gnu/local.mk | 4 +- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 99 ++-- 4 files changed, 557 insertions(+), 37 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 98f2d4ac30..cf34905431 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1749,6 +1749,8 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..abf253486f --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/share/pkgs/gui-lib/mred/installer.rkt ++++ b/share/pkgs/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ec9e836a4c..00ec587eeb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -43,6 +43,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages libedit) #:use-module (gnu packages libffi) #:use-module (gnu packages multiprecision) + #:use-module (gnu packages ncurses) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) #:use-module (gnu packages xorg) @@ -95,6 +96,41 @@ (define-module (gnu packages racket) ;; ;; Code: +(define %racket-version "8.4") +;; ^ Remember to update racket-bootstrap-chez-bootfiles! +(define %racket-commit + (string-append "v" %racket-version)) +(define %racket-origin + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit %racket-commit))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" %racket-version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + (use-modules (guix build utils)) + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + ;; TODO: consider putting this in a (guix ...) or (guix build ...) + ;; module so it can be shared with the upstream Chez Scheme origin + ;; without cyclic issues. + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (define cfg-flag:sh-for-rktio `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" (assoc-ref %build-inputs "sh") @@ -128,41 +164,17 @@ (define src (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) + (version %racket-version) + (source %racket-origin) (inputs `(;; common to all racket-minimal variants: ("openssl" ,openssl) ("sqlite" ,sqlite) - ("sh" ,bash-minimal) + ("sh" ,bash-minimal) ;; <- for `system` + ("ncurses" ,ncurses) ;; <- for #%terminal ;; only for CS ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) + ("lz4" ,lz4))) (native-inputs `(("bootfiles" ,racket-bootstrap-chez-bootfiles) ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) @@ -263,9 +275,8 @@ (define-public racket-minimal-bc-3m (name "racket-minimal-bc-3m") (inputs (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) + (prepend libffi) ;; <- only for BC variants + (delete "zlib" "lz4"))) (native-inputs `(("libtool" ,libtool) ("racket" ,(if (%current-target-system) @@ -327,6 +338,11 @@ (define-public racket-bootstrap-chez-bootfiles (package (inherit racket-minimal) (name "racket-bootstrap-chez-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. (inputs `()) (native-inputs `(("racket" ,(if (%current-target-system) @@ -416,7 +432,7 @@ (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work + (version %racket-version) (source (origin (method url-fetch) @@ -425,7 +441,11 @@ (define-public racket %installer-mirrors)) (sha256 (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) + "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) (snippet #~(begin (use-modules (guix build utils) @@ -442,7 +462,14 @@ (define-public racket (with-directory-excursion "share/pkgs" (for-each delete-file-recursively '#+%main-repo-main-distribution-pkgs)) - #t)))) + ;; Minimal workaround for FSDG issue: + ;; see <https://github.com/racket/srfi/pull/15>. + ;; We will backport a better fix once we use Git + ;; origins for Racket packages. + (delete-file-recursively "share/pkgs/srfi-doc-nonfree") + (substitute* "share/pkgs/srfi/info.rkt" + (("\"srfi-doc-nonfree\"") + "")))))) (inputs `(("cairo" ,cairo) ("fontconfig" ,fontconfig) @@ -461,7 +488,7 @@ (define-public racket (native-inputs `(("racket" ,racket-minimal) ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + ("main-repo" ,%racket-origin))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 02/24] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 8:42 ` Liliana Marie Prikler 2022-02-27 2:34 ` [bug#53878] [PATCH v6 04/24] gnu: racket-minimal: Use new package style Philip McGrath ` (20 subsequent siblings) 23 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: Adjust path. * gnu/packages/racket.scm (racket-packages-origin, simple-racket-origin): New procedures. (extend-layer): Rename to ... (configure-layer.rkt): ... this variable. Tweak command-line arguments. Adapt to 'config-tethered-apps-dir'. (racket): Stop inheriting from 'racket-minimal'. [version]: Use '%racket-version'. [source]: Stop using bundled tarball. [inputs]: Remove labels. Add 'racket-minimal' and package sources. [native-inputs]: Remove, since cross-compilation doesn't work yet. [arguments]: Rewrite to use G-expressions, package sources from 'inputs', an explicit 'install' phase, and the revised 'configure-layer.rkt'. --- ...acket-gui-tethered-launcher-backport.patch | 6 +- gnu/packages/racket.scm | 714 +++++++++++++----- 2 files changed, 539 insertions(+), 181 deletions(-) diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch index abf253486f..1e018eaa79 100644 --- a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -7,13 +7,13 @@ Related to racket/racket#4133 (cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) --- - share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + gui-lib/mred/installer.rkt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt index b1691472..9ef06c53 100644 ---- a/share/pkgs/gui-lib/mred/installer.rkt -+++ b/share/pkgs/gui-lib/mred/installer.rkt +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt @@ -72,4 +72,5 @@ (list "-A" (path->string (find-system-path 'addon-dir))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 00ec587eeb..c4e5ee1311 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -28,7 +28,9 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -389,172 +391,504 @@ (define-public racket-bootstrap-chez-bootfiles Chez Scheme.") (license (list license:asl2.0))))) +(define (racket-packages-origin name origin spec0 . spec*) + "Extract from ORIGIN the sources for the Racket packages specified by SPEC0 +and any additional arguments SPEC*. In the resulting file-like object, each +package's source will be in the directory \"/share/racket/pkgs/PKG/\", where +PKG is the Racket name for the package. The NAME will be used in the store +file name for the resulting file-like object. -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) +A package specification is a list of the form: -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) + (PKG PATH) +where PATH is the path to the package source relative to ORIGIN---possibly +\".\". As a special case, a package specification may also be a string, which +is equivalent to: + + (PKG PKG) + +Examples: + +- \"expeditor\" +- (\"main-distribution\" \".\") +- (\"racket-lib\" \"pkgs/racket-lib\")" + (computed-file + (string-append "racket-pkg-" name "-sources") + (with-imported-modules `((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p (string-append #$output "/share/racket/pkgs")) + (chdir (string-append #$output "/share/racket/pkgs")) + #$@(map (match-lambda + ((? string? name) + #~(copy-recursively #$(file-append origin (string-append "/" name)) + #$name)) + ((name ".") + #~(copy-recursively #$origin #$name)) + ((name path) + #~(copy-recursively #$(file-append origin (string-append "/" path)) + #$name))) + (cons spec0 spec*)))))) + +(define (simple-racket-origin repo hash spec0 . spec*) + "Like 'racket-packages-origin', but specialized for packages hosted at +\"https://github.com/racket/REPO\" with sha256 checksum HASH. REPO is also +used to build the name of the resulting store item." + (apply racket-packages-origin + repo + (origin + (method git-fetch) + (uri (git-reference + (url (format #f "https://github.com/racket/~a" repo)) + (commit %racket-commit))) + (sha256 hash) + (file-name (git-file-name (string-append "racket-" repo) + %racket-version))) + spec0 + spec*)) (define-public racket (package - (inherit racket-minimal) (name "racket") (version %racket-version) - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) - (patches - ;; remove in Racket 8.5 - ;; see https://github.com/racket/racket/issues/4133 - (search-patches "racket-gui-tethered-launcher-backport.patch")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - ;; Minimal workaround for FSDG issue: - ;; see <https://github.com/racket/srfi/pull/15>. - ;; We will backport a better fix once we use Git - ;; origins for Racket packages. - (delete-file-recursively "share/pkgs/srfi-doc-nonfree") - (substitute* "share/pkgs/srfi/info.rkt" - (("\"srfi-doc-nonfree\"") - "")))))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,%racket-origin))) + (list + cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (simple-racket-origin + "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") + "2d" "2d-doc" "2d-lib") + (simple-racket-origin + "algol60" (base32 "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx") + '("algol60" ".")) + (racket-packages-origin + "racket" %racket-origin + '("base" "pkgs/base") ;; FIXME belongs in racket-minimal + '("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal + '("at-exp-lib" "pkgs/at-exp-lib") + '("compiler" "pkgs/compiler") + '("compiler-lib" "pkgs/compiler-lib") + '("net" "pkgs/net") + '("net-doc" "pkgs/net-doc") + '("net-lib" "pkgs/net-lib") + '("racket-doc" "pkgs/racket-doc") + '("racket-index" "pkgs/racket-index") + '("sandbox-lib" "pkgs/sandbox-lib") + '("zo-lib" "pkgs/zo-lib")) + (simple-racket-origin + "cext-lib" (base32 "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341") + "cext-lib" "dynext-lib") + (simple-racket-origin + "class-iop" (base32 "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l") + "class-iop-lib") + (simple-racket-origin + "compatibility" (base32 "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0") + "compatibility" "compatibility-doc" "compatibility-lib") + (simple-racket-origin + "contract-profile" (base32 "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3") + '("contract-profile" ".")) + (simple-racket-origin + "data" (base32 "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55") + "data" "data-doc" "data-enumerate-lib" "data-lib") + (simple-racket-origin + "datalog" (base32 "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp") + '("datalog" ".")) + (simple-racket-origin + "db" (base32 "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5") + "db" "db-doc" "db-lib") + (simple-racket-origin + "deinprogramm" (base32 "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd") + "deinprogramm" "deinprogramm-signature") + (simple-racket-origin + "distributed-places" (base32 "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0") + "distributed-places" "distributed-places-doc" "distributed-places-lib") + (simple-racket-origin + "draw" (base32 "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly") + "draw" "draw-doc" "draw-lib") + (simple-racket-origin + "drracket" (base32 "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c") + "drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib") + (simple-racket-origin + "ds-store" (base32 "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661") + "ds-store" "ds-store-doc" "ds-store-lib") + (simple-racket-origin + "eli-tester" (base32 "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk") + '("eli-tester" ".")) + (simple-racket-origin + "eopl" (base32 "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s") + '("eopl" ".")) + (simple-racket-origin + "errortrace" (base32 "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip") + "errortrace" "errortrace-doc" "errortrace-lib") + (simple-racket-origin + "expeditor" (base32 "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf") + "expeditor" "expeditor-doc" "expeditor-lib") + (simple-racket-origin + "frtime" (base32 "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5") + '("frtime" ".")) + (simple-racket-origin + "future-visualizer" (base32 "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm") + "future-visualizer" + "future-visualizer-pict" + "future-visualizer-typed") + (simple-racket-origin + "games" (base32 "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d") + '("games" ".")) + (racket-packages-origin + "gui" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + "gui" "gui-doc" "gui-lib" "tex-table") + (simple-racket-origin + "gui-pkg-manager" (base32 "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5") + "gui-pkg-manager-lib") + (simple-racket-origin + "htdp" (base32 "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl") + "htdp" "htdp-doc" "htdp-lib") + (simple-racket-origin + "html" (base32 "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x") + "html" "html-doc" "html-lib") + (simple-racket-origin + "icons" (base32 "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7") + '("icons" ".")) + (simple-racket-origin + "images" (base32 "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl") + "images" "images-doc" "images-gui-lib" "images-lib") + (simple-racket-origin + "lazy" (base32 "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf") + '("lazy" ".")) + (simple-racket-origin + "macro-debugger" (base32 "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm") + "macro-debugger" "macro-debugger-text-lib") + (simple-racket-origin + "main-distribution" (base32 "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y") + '("main-distribution" ".")) + (simple-racket-origin + "make" (base32 "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa") + '("make" ".")) + (simple-racket-origin + "math" (base32 "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac") + "math" "math-doc" "math-lib") + (simple-racket-origin + "mysterx" (base32 "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48") + '("mysterx" ".")) + (simple-racket-origin + "mzcom" (base32 "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4") + '("mzcom" ".")) + (simple-racket-origin + "mzscheme" (base32 "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9") + "mzscheme" "mzscheme-doc" "mzscheme-lib") + (racket-packages-origin + "net-cookies" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + "net-cookies" "net-cookies-doc" "net-cookies-lib") + (racket-packages-origin + "optimization-coach" + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + '("optimization-coach" ".")) + (simple-racket-origin + "option-contract" (base32 "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk") + "option-contract" "option-contract-doc" "option-contract-lib") + (simple-racket-origin + "parser-tools" (base32 "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3") + "parser-tools" "parser-tools-doc" "parser-tools-lib") + (simple-racket-origin + "pconvert" (base32 "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1") + "pconvert-lib") + (simple-racket-origin + "pict" (base32 "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x") + "pict" "pict-doc" "pict-lib") + (simple-racket-origin + "pict-snip" (base32 "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x") + "pict-snip" "pict-snip-doc" "pict-snip-lib") + (simple-racket-origin + "picturing-programs" (base32 "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr") + '("picturing-programs" ".")) + (simple-racket-origin + "plai" (base32 "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl") + "plai" "plai-doc" "plai-lib") + (simple-racket-origin + "planet" (base32 "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9") + "planet" "planet-doc" "planet-lib") + (simple-racket-origin + "plot" (base32 "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7") + "plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib") + (simple-racket-origin + "preprocessor" (base32 "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg") + '("preprocessor" ".")) + (simple-racket-origin + "profile" (base32 "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb") + "profile" "profile-doc" "profile-lib") + (racket-packages-origin + "quickscript" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + '("quickscript" ".")) + (simple-racket-origin + "r5rs" (base32 "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6") + "r5rs" "r5rs-doc" "r5rs-lib") + (simple-racket-origin + "r6rs" (base32 "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4") + "r6rs" "r6rs-doc" "r6rs-lib") + (racket-packages-origin + "racket-cheat" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + '("racket-cheat" ".")) + (simple-racket-origin + "racklog" (base32 "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb") + '("racklog" ".")) + (simple-racket-origin + "rackunit" (base32 "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p") + "rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib") + (simple-racket-origin + "readline" (base32 "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn") + "readline" "readline-doc" "readline-lib") + (simple-racket-origin + "realm" (base32 "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi") + '("realm" ".")) + (simple-racket-origin + "redex" (base32 "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f") + "redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib") + (simple-racket-origin + "sasl" (base32 "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824") + "sasl" "sasl-doc" "sasl-lib") + (simple-racket-origin + "scheme-lib" (base32 "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x") + '("scheme-lib" ".")) + (simple-racket-origin + "scribble" (base32 "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm") + "scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib") + (simple-racket-origin + "serialize-cstruct-lib" + (base32 "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz") + '("serialize-cstruct-lib" ".")) + (simple-racket-origin + "sgl" (base32 "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv") + '("sgl" ".")) + (simple-racket-origin + "shell-completion" (base32 "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj") + '("shell-completion" ".")) + (simple-racket-origin + "simple-tree-text-markup" + (base32 "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr") + "simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib") + (simple-racket-origin + "slatex" (base32 "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0") + '("slatex" ".")) + (simple-racket-origin + "slideshow" (base32 "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm") + "slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" "slideshow-plugin") + (simple-racket-origin + "snip" (base32 "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj") + "snip" "snip-lib") + (simple-racket-origin + "typed-racket" (base32 "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv") + "source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more") + (racket-packages-origin + "srfi" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + "srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib") + (simple-racket-origin + "string-constants" (base32 "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6") + "string-constants" "string-constants-doc" "string-constants-lib") + (simple-racket-origin + "swindle" (base32 "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67") + '("swindle" ".")) + (simple-racket-origin + "syntax-color" (base32 "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp") + "syntax-color" "syntax-color-doc" "syntax-color-lib") + (simple-racket-origin + "trace" (base32 "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia") + '("trace" ".")) + (simple-racket-origin + "unix-socket" (base32 "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y") + "unix-socket" "unix-socket-doc" "unix-socket-lib") + (simple-racket-origin + "web-server" (base32 "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn") + "web-server" "web-server-doc" "web-server-lib") + (simple-racket-origin + "wxme" (base32 "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b") + "wxme" "wxme-lib") + (simple-racket-origin + "xrepl" (base32 "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3") + "xrepl" "xrepl-doc" "xrepl-lib"))) + (build-system gnu-build-system) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + ;; We're using #:configure-flags to pass flags for + ;; `configure-layer.rkt` and #:make-flags to pass arguments for + ;; `raco pkg install`. + (list + #:configure-flags + #~`("--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit"))))) + #:make-flags #~`("main-distribution") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((racket (search-input-file inputs "bin/racket"))) + (apply invoke + racket + #$configure-layer.rkt + `(,@configure-flags + ,(dirname (dirname racket)) + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket (search-input-file inputs "/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -564,17 +898,20 @@ (define dest (string-append pkgs-dir "/" pkg)) The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) -(define extend-layer +(define configure-layer.rkt (scheme-file - "extend-layer.rkt" + "configure-layer.rkt" `(module - extend-layer racket/base + configure-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) (define config-file-pth @@ -584,8 +921,14 @@ (define (build-path-string . args) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define extra-foreign-lib-search-dirs '()) (command-line - #:args (parent-layer prefix . lib-dir*) + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) (let* ([config (for/fold ([config (file->value (build-path parent-layer @@ -615,27 +958,42 @@ (define rx:racket (build-path-string parent-layer pth)) (filter values (hash-ref config search-key null)))))] [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config - 'lib-search-dirs - (append rkt - lib-dir* - extra)))] + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaround Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] [bin-dir (hash-ref config 'bin-dir)] [config (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) 'config-tethered-console-bin-dir bin-dir 'config-tethered-gui-bin-dir bin-dir)] [new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath @ 2022-02-27 8:42 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-27 8:42 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Hi, Am Samstag, dem 26.02.2022 um 21:34 -0500 schrieb Philip McGrath: > * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: > Adjust path. > * gnu/packages/racket.scm (racket-packages-origin, > simple-racket-origin): New procedures. > (extend-layer): Rename to ... > (configure-layer.rkt): ... this variable. Tweak command-line > arguments. Adapt to 'config-tethered-apps-dir'. > (racket): Stop inheriting from 'racket-minimal'. > [version]: Use '%racket-version'. > [source]: Stop using bundled tarball. > [inputs]: Remove labels. Add 'racket-minimal' and package sources. > [native-inputs]: Remove, since cross-compilation doesn't work yet. > [arguments]: Rewrite to use G-expressions, package sources from > 'inputs', an explicit 'install' phase, and the revised > 'configure-layer.rkt'. > --- > ...acket-gui-tethered-launcher-backport.patch | 6 +- > gnu/packages/racket.scm | 714 +++++++++++++--- > -- > 2 files changed, 539 insertions(+), 181 deletions(-) > > diff --git a/gnu/packages/patches/racket-gui-tethered-launcher- > backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher- > backport.patch > index abf253486f..1e018eaa79 100644 > --- a/gnu/packages/patches/racket-gui-tethered-launcher- > backport.patch > +++ b/gnu/packages/patches/racket-gui-tethered-launcher- > backport.patch > @@ -7,13 +7,13 @@ Related to racket/racket#4133 > > (cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) > --- > - share/pkgs/gui-lib/mred/installer.rkt | 3 ++- > + gui-lib/mred/installer.rkt | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt > index b1691472..9ef06c53 100644 > ---- a/share/pkgs/gui-lib/mred/installer.rkt > -+++ b/share/pkgs/gui-lib/mred/installer.rkt > +--- a/gui-lib/mred/installer.rkt > ++++ b/gui-lib/mred/installer.rkt > @@ -72,4 +72,5 @@ > (list "-A" (path->string (find-system-path 'addon-dir))))) > > diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm > index 00ec587eeb..c4e5ee1311 100644 > --- a/gnu/packages/racket.scm > +++ b/gnu/packages/racket.scm > @@ -28,7 +28,9 @@ (define-module (gnu packages racket) > #:use-module (guix gexp) > #:use-module (guix build-system gnu) > #:use-module (srfi srfi-1) > + #:use-module (srfi srfi-26) > #:use-module (ice-9 match) > + #:use-module (ice-9 exceptions) > #:use-module (gnu packages) > #:use-module (gnu packages autotools) > #:use-module (gnu packages bash) > @@ -389,172 +391,504 @@ (define-public racket-bootstrap-chez- > bootfiles > Chez Scheme.") > (license (list license:asl2.0))))) > > +(define (racket-packages-origin name origin spec0 . spec*) > + "Extract from ORIGIN the sources for the Racket packages specified > by SPEC0 > +and any additional arguments SPEC*. In the resulting file-like > object, each > +package's source will be in the directory > \"/share/racket/pkgs/PKG/\", where > +PKG is the Racket name for the package. The NAME will be used in > the store > +file name for the resulting file-like object. > > -(define %installer-mirrors > - ;; Source: > - ;; > https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 > - ;; Matthew Flatt says: "note that many are commented out" > - ;; INVARIANT: End with a trailing "/"! > - '("https://mirror.racket-lang.org/installers/" > - "https://www.cs.utah.edu/plt/installers/" > - "https://plt.cs.northwestern.edu/racket-mirror/" > - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" > - ;; Universität Tübingen is using a self-signed HTTPS > certificate: > - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" > - "https://racket.infogroep.be/" > - )) > +A package specification is a list of the form: > > -(define %main-repo-main-distribution-pkgs > - ;; These are the packages developed in the main Racket Git > repository > - ;; that are part of the main distribution. > - '("at-exp-lib" > - "base" > - "compiler-lib" > - ;; NOT "compiler-test" > - "compiler" > - "net-doc" > - "net-lib" > - ;; NOT "net-test" > - "net" > - ;; NOT "plt-services" > - ;; NOT "racket-benchmarks" > - ;; NOT "racket-build-guide" > - "racket-doc" > - "racket-index" > - "racket-lib" > - ;; NOT "racket-test-core" > - ;; NOT "racket-test-extra" > - ;; NOT "racket-test" > - "zo-lib")) > + (PKG PATH) > > +where PATH is the path to the package source relative to ORIGIN--- > possibly > +\".\". As a special case, a package specification may also be a > string, which > +is equivalent to: > + > + (PKG PKG) > + > +Examples: > + > +- \"expeditor\" > +- (\"main-distribution\" \".\") > +- (\"racket-lib\" \"pkgs/racket-lib\")" > + (computed-file > + (string-append "racket-pkg-" name "-sources") > + (with-imported-modules `((guix build utils)) > + #~(begin > + (use-modules (guix build utils)) > + (mkdir-p (string-append #$output "/share/racket/pkgs")) > + (chdir (string-append #$output "/share/racket/pkgs")) > + #$@(map (match-lambda > + ((? string? name) > + #~(copy-recursively #$(file-append origin > (string-append "/" name)) > + #$name)) > + ((name ".") > + #~(copy-recursively #$origin #$name)) > + ((name path) > + #~(copy-recursively #$(file-append origin > (string-append "/" path)) > + #$name))) > + (cons spec0 spec*)))))) Perhaps I wasn't clear enough about this in v5, but I think spec should be a single argument rather than multiple ones. This way, if we do find that we need to extend it to support an additional argument, we don't have to awkwardly code around the #:rest. > +(define (simple-racket-origin repo hash spec0 . spec*) > + "Like 'racket-packages-origin', but specialized for packages > hosted at > +\"https://github.com/racket/REPO\" with sha256 checksum HASH. REPO > is also > +used to build the name of the resulting store item." > + (apply racket-packages-origin > + repo > + (origin > + (method git-fetch) > + (uri (git-reference > + (url (format #f "https://github.com/racket/~a" > repo)) > + (commit %racket-commit))) > + (sha256 hash) > + (file-name (git-file-name (string-append "racket-" repo) > + %racket-version))) > + spec0 > + spec*)) Same here, plus it saves us the trouble of a additional "apply". The effect for > + (simple-racket-origin > + "2d" (base32 > "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") > + "2d" "2d-doc" "2d-lib") would be that '("2d" "2d-doc" "2d-lib") is more clearly delimited from the package name and hash, and > + (racket-packages-origin > + "racket" %racket-origin > + '("base" "pkgs/base") ;; FIXME belongs in racket-minimal > + '("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket- > minimal > + '("at-exp-lib" "pkgs/at-exp-lib") > + '("compiler" "pkgs/compiler") > + '("compiler-lib" "pkgs/compiler-lib") > + '("net" "pkgs/net") > + '("net-doc" "pkgs/net-doc") > + '("net-lib" "pkgs/net-lib") > + '("racket-doc" "pkgs/racket-doc") > + '("racket-index" "pkgs/racket-index") > + '("sandbox-lib" "pkgs/sandbox-lib") > + '("zo-lib" "pkgs/zo-lib")) '(("base" "pkgs/base") ("racket-lib" "pkgs/racket-lib") ...) needs less quoting over-all. > + (simple-racket-origin > + "class-iop" (base32 > "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l") > + "class-iop-lib") While single strings like this do each cost three additional characters that way, I wouldn't special-case them. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 04/24] gnu: racket-minimal: Use new package style. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (2 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath ` (19 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (cfg-flag:sh-for-rktio, cfg-flag:enable-lt, cfg-glag:enable-racket): Change to G-expressions and combine in ... (racket-vm-common-configure-flags): ... this new thunk. (unpack-nanopass+stex): Change to G-expression and move to ... (make-unpack-nanopass+stex): ... this new thunk. (racket-bootstrap-chez-bootfiles): Rename to ... (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable, and stop inheriting from 'racket-minimal'. [native-inputs]: Remove labels. [build-system]: Use 'copy-build-system'. [arguments]: Use G-expressions. Install under "lib". (racket-minimal)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. Avoid 'assoc-ref'. Adapt to changes in 'chez-scheme-for-racket-bootstrap-bootfiles'. (racket-minimal-bc-3m)[native-inputs]: Remove labels. [arguments]: Use G-expressions. (racket-minimal-bc-cgc)[native-inputs]: Remove labels. [arguments]: Use G-expressions. --- gnu/packages/racket.scm | 332 ++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 169 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index c4e5ee1311..55fdb28fdd 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -26,6 +26,7 @@ (define-module (gnu packages racket) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) @@ -99,7 +100,7 @@ (define-module (gnu packages racket) ;; Code: (define %racket-version "8.4") -;; ^ Remember to update racket-bootstrap-chez-bootfiles! +;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin @@ -133,34 +134,42 @@ (define %racket-origin ;; Unbundle libffi. (delete-file-recursively "racket/src/bc/foreign/libffi"))))) -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) +(define (racket-vm-common-configure-flags) + ;; under a lambda abstraction to avoid evaluating bash-minimal too early. + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")))) -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) +(define (make-unpack-nanopass+stex) + ;; Adapted from chez-scheme. + ;; Thunked to avoid evaluating 'chez-scheme' too early. + ;; TODO: Refactor enough to share this directly. + #~(begin + (copy-recursively + #$(match (assoc-ref (package-native-inputs chez-scheme) + "nanopass") + ((src) + src)) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) (define-public racket-minimal @@ -169,91 +178,87 @@ (define-public racket-minimal (version %racket-version) (source %racket-origin) (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) ;; <- for `system` - ("ncurses" ,ncurses) ;; <- for #%terminal - ;; only for CS - ("zlib" ,zlib) - ("lz4" ,lz4))) + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for CS + zlib + lz4)) (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (list chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m)) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) + (list + #:configure-flags + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) (guix build gnu-build-system) (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))) + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs + . (,(string-append + "https://download.racket-lang.org/releases/" + #$(package-version this-package) + "/catalog/") + #f)))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -269,7 +274,6 @@ (define (write-racket-hash alist) ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) - (define-public racket-minimal-bc-3m (hidden-package (package @@ -280,21 +284,19 @@ (define-public racket-minimal-bc-3m (prepend libffi) ;; <- only for BC variants (delete "zlib" "lz4"))) (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) + (list libtool + (if (%current-target-system) + racket-minimal + racket-minimal-bc-cgc))) (arguments (substitute-keyword-arguments (package-arguments racket-minimal) ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))) + ((#:phases cs-phases) + #~(modify-phases #$cs-phases + (delete 'unpack-nanopass+stex) + (delete 'unpack-bootfiles))))) (synopsis "Minimal Racket with the BC [3M] runtime system") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written @@ -309,19 +311,16 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) - (define-public racket-minimal-bc-cgc (package (inherit racket-minimal-bc-3m) (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) + (native-inputs (list libtool)) (arguments (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags))))) (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or ``bytecode'') implementation is not recommended for general use. It uses @@ -334,47 +333,42 @@ (define-public racket-minimal-bc-cgc also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector."))) - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source %racket-origin) + (inputs `()) + (native-inputs (list racket-minimal-bc-3m)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$(make-unpack-nanopass+stex))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/bin/racket") + "rktboot/main.rkt")))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it requires ``bootfiles'' containing the Scheme-implemented portions compiled for the current platform. (Chez can then cross-compile bootfiles for all other supported platforms.) @@ -389,7 +383,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list license:asl2.0))))) + (license (list license:asl2.0)))) (define (racket-packages-origin name origin spec0 . spec*) "Extract from ORIGIN the sources for the Racket packages specified by SPEC0 -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 05/24] gnu: racket-minimal: Don't configure non-existant catalogs. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (3 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 04/24] gnu: racket-minimal: Use new package style Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath ` (18 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal)[arguments]<#:phases>: Change 'initialize-config.rktd' to only add a release catalog when the package version is a release version. --- gnu/packages/racket.scm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 55fdb28fdd..b828bbbd3d 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -231,6 +231,15 @@ (define (write-racket-hash alist) (format #t "(~s . ~s)" k v))) alist) (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) (mkdir-p "racket/etc") (with-output-to-file "racket/etc/config.rktd" (lambda () @@ -239,12 +248,8 @@ (define (write-racket-hash alist) . (#f #$(file-append (this-package-input "openssl") "/lib") #$(file-append (this-package-input "sqlite") "/lib"))) (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - #$(package-version this-package) - "/catalog/") - #f)))))))) + (catalogs ,@maybe-release-catalog + #f))))))) (add-before 'configure 'chdir (lambda _ (chdir "racket/src"))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (4 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath ` (17 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Having the package inheritance chain go in the same direction as the bootstrapping chain, rather than the opposite, is less confusing. In some cases, it can also help to avoid unnecessary rebuilds. * gnu/packages/racket.scm (racket-minimal-bc-cgc): Change to be the root of the package inheritance chain. [version, source, inputs, native-inputs, build-system, arguments, home-page, license]: Inline formerly inherited values. (racket-minimal-bc-3m): Inherit from 'racket-minimal-bc-cgc' rather than 'racket-minimal'. [inputs, native-inputs, arguments, license]: Adjust accordingly. (racket-minimal): Inherit from 'racket-minimal-bc-3m'. [inputs, native-inputs, arguments, license]: Adjust accordingly. [properties]: Override effect of 'hidden-package'. --- gnu/packages/racket.scm | 130 +++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 63 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index b828bbbd3d..00f4fef49f 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -172,9 +172,9 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal +(define-public racket-minimal-bc-cgc (package - (name "racket-minimal") + (name "racket-minimal-bc-cgc") (version %racket-version) (source %racket-origin) (inputs @@ -184,19 +184,14 @@ (define-public racket-minimal sqlite bash-minimal ;; <- for `system` ncurses ;; <- for #%terminal - ;; only for CS - zlib - lz4)) - (native-inputs - (list chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m)) + ;; only for BC variants: + libffi)) + (native-inputs (list libtool)) ;; <- only for BC variants (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-csonly" - "--enable-libz" - "--enable-lz4" + #~(cons* "--enable-cgcdefault" #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main @@ -210,17 +205,6 @@ (define-public racket-minimal (guix build utils)) #:phases #~(modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))) (add-before 'configure 'initialize-config.rktd (lambda* (#:key inputs #:allow-other-keys) (define (write-racket-hash alist) @@ -265,43 +249,37 @@ (define maybe-release-catalog ;; rmdir because we want an error if it isn't empty (rmdir (string-append #$output "/share/racket/pkgs"))))))) (home-page "https://racket-lang.org") - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") +Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) + (license (list license:lgpl3+ license:asl2.0 license:expat)) + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (properties `((hidden? . #t))))) (define-public racket-minimal-bc-3m (hidden-package (package - (inherit racket-minimal) + (inherit racket-minimal-bc-cgc) (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (prepend libffi) ;; <- only for BC variants - (delete "zlib" "lz4"))) (native-inputs - (list libtool - (if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (prepend racket-minimal-bc-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) + (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" - #$(racket-vm-common-configure-flags))) - ((#:phases cs-phases) - #~(modify-phases #$cs-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) + #$(racket-vm-common-configure-flags))))) (synopsis "Minimal Racket with the BC [3M] runtime system") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written @@ -316,27 +294,53 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-cgc +(define-public racket-minimal (package (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs (list libtool)) + (name "racket-minimal") + (inputs + (modify-inputs (package-inputs racket-minimal-bc-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m))) (arguments (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) + ((#:phases bc-phases) + #~(modify-phases #$bc-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))))) ((#:configure-flags _ '()) - #~(cons "--enable-cgcdefault" - #$(racket-vm-common-configure-flags))))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + (properties `()) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) (define-public chez-scheme-for-racket-bootstrap-bootfiles (package -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 07/24] gnu: racket-minimal: Adjust indentation. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (5 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath ` (16 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal-bc-cgc): Use 'hidden-package' rather than 'properties'. (racket-minimal-bc-3m): Remove redundant 'hidden-package' wrapper. --- gnu/packages/racket.scm | 201 ++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 101 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 00f4fef49f..ca0c09be58 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -173,84 +173,87 @@ (define (make-unpack-nanopass+stex) (define-public racket-minimal-bc-cgc - (package - (name "racket-minimal-bc-cgc") - (version %racket-version) - (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) - (native-inputs (list libtool)) ;; <- only for BC variants - (build-system gnu-build-system) - (arguments - (list - #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main - ;; distribution. - #:tests? #f - ;; Upstream recommends #:out-of-source?, and it does - ;; help with debugging, but it confuses `install-license-files`. - #:modules '((ice-9 match) - (ice-9 regex) - (guix build gnu-build-system) - (guix build utils)) - #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) - (home-page "https://racket-lang.org") - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-minimal-bc-cgc") + (version %racket-version) + (source %racket-origin) + (inputs + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for BC variants: + libffi)) + (native-inputs (list libtool)) ;; <- only for BC variants + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons* "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:phases + #~(modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or ``bytecode'') implementation is not recommended for general use. It uses CGC (a ``Conservative Garbage Collector''), which was succeeded as default in PLT Scheme version 370 (which translates to 3.7 in the current versioning @@ -260,28 +263,24 @@ (define maybe-release-catalog Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:lgpl3+ license:asl2.0 license:expat)) - ;; Eventually, it may make sense for some vm packages to not be hidden, - ;; but this one is especially likely to remain hidden. - (properties `((hidden? . #t))))) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) (define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") - (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) - ((#:configure-flags _ '()) - #~(cons "--enable-bconly" - #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') + (package + (inherit racket-minimal-bc-cgc) + (name "racket-minimal-bc-3m") + (native-inputs + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (prepend racket-minimal-bc-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Minimal Racket with the BC [3M] runtime system") + (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different @@ -290,9 +289,9 @@ (define-public racket-minimal-bc-3m This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:lgpl3+ license:asl2.0 license:expat))))) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat)))) (define-public racket-minimal (package -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 08/24] gnu: racket-minimal: Add "debug" output. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (6 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath ` (15 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal-bc-cgc)[outputs]: Add "debug". (racket-vm-common-configure-flags): Add "--disable-strip". --- gnu/packages/racket.scm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ca0c09be58..69c99f5764 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -151,7 +151,8 @@ (define (racket-vm-common-configure-flags) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - #$(file-append bash-minimal "/bin/sh")))) + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -190,6 +191,7 @@ (define-public racket-minimal-bc-cgc ;; only for BC variants: libffi)) (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 09/24] gnu: configure-layer.rkt: Adjust indentation. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (7 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath ` (14 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (configure-layer.rkt): Wrap 'command-line' in 'define-values' to reduce rightward drift. --- gnu/packages/racket.scm | 164 ++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 69c99f5764..4f5f0c1df2 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -926,84 +926,86 @@ (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) (define extra-foreign-lib-search-dirs '()) - (command-line - #:once-each - [("--extra-foreign-lib-search-dirs") dir-list - "foreign library directories, as a list of strings in `read` syntax" - (set! extra-foreign-lib-search-dirs - (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-update config - 'lib-search-dirs - (lambda (dirs) - ;; add after other layers, but before older - ;; foreign lib search directories - (define-values [rkt old-foreign-dirs] - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - dirs)) - (append rkt - extra-foreign-lib-search-dirs - old-foreign-dirs)))] - [config - (hash-set* config - 'apps-dir - (build-path-string prefix "share/applications") - 'absolute-installation? #t - ;; Let Guix coexist with other installation - ;; methods without clobbering user-specific packages. - ;; This could be set in various places, but doing - ;; it here is convienient, at least until we support - ;; cross-compilation. - 'installation-name - (string-append (version) - "-guix" - (match (system-type 'gc) - ['cgc "-cgc"] - ;; workaround Guile reader/printer: - ['|3m| "-bc"] - [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (define-values [parent-layer prefix] + (command-line + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) + (values parent-layer prefix))) + (let* ([config + (for/fold + ([config (file->value (build-path parent-layer + config-file-pth))]) + ([spec (in-list + '((lib-dir lib-search-dirs "lib/racket") + (share-dir share-search-dirs "share/racket") + (links-file + links-search-files + "share/racket/links.rktd") + (pkgs-dir pkgs-search-dirs "share/racket/pkgs") + (bin-dir bin-search-dirs "bin") + (man-dir man-search-dirs "share/man") + (doc-dir doc-search-dirs "share/doc/racket") + (include-dir + include-search-dirs + "include/racket")))]) + (match-define (list main-key search-key pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (build-path-string parent-layer pth)) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaround Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [bin-dir + (hash-ref config 'bin-dir)] + [config + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [new-config-pth + (build-path prefix config-file-pth)]) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 10/24] gnu: racket-minimal: Separate from the Racket VM. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (8 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath ` (13 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes For consistency with other Racket distributions, 'racket-minimal' should have the "racket-lib" Racket package installed: see <https://github.com/racket/racket/issues/3851#issuecomment-942368947>. Happily, this gives us a clean boundary between the core Racket VM and compiler, with all of the bootstrapping involved, and building Racket packages and installation layers, which can be handled in a nice, uniform way and eventually turned into a 'racket-build-system'. Building the VM layer as an "in-place" installation should help us use it with other Racket tools. * gnu/packages/racket.scm (racket-vm-common-configure-flags): Add "--enable-origtree". Adapt "--enable-racket=" for "opt/racket-vm/" prefix. (racket-minimal-bc-cgc): Rename to ... (racket-vm-cgc): ... this new variable. [inputs]: Move 'openssl' and 'sqlite' to new 'racket-minimal'. [arguments]<#:strip-directories>: Use "opt/racket-vm/" prefix. <#:phases>: Wrap 'configure', 'patch-shebangs', 'validate-runpath', 'make-dynamic-linker-cache', and 'patch-dot-desktop-files' to use "opt/racket-vm/" prefix. Adapt 'initialize-config.rktd' for removal of 'openssl' and 'sqlite'. [description]: Tweak. (racket-minimal-bc-3m): Rename to ... (racket-vm-bc): ... this new variable. [synopsis, description]: Tweak. (racket-vm-cs): New variable, adapted from the old 'racket-minimal'. (chez-scheme-for-racket-bootstrap-bootfiles)[arguments]<#:phhases>: Adapt to the "opt/racket-vm/" prefix. (racket-minimal): Rewrite like 'racket' using 'racket-vm-cs'. (racket): Inherit from 'racket-minimal'. [inputs]: Add 'racket-vm-cs'. Move "racket-lib" and "base" to 'racket-minimal'. [arguments]<#:make-flags, #:configure-flags>: Override from 'racket-minimal'. (configure-layer.rkt): Adapt to support in-place VM build with possible intermediate layer. --- gnu/packages/racket.scm | 597 ++++++++++++++++++++++++++-------------- 1 file changed, 385 insertions(+), 212 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 4f5f0c1df2..3271e78d45 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -54,7 +54,91 @@ (define-module (gnu packages racket) ;; Commentary: ;; -;; Here's how bootstrapping minimal Racket works: +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: ;; ;; - Racket BC [CGC] can be built with only a C compiler (except for ;; one caveat discussed below). @@ -72,6 +156,10 @@ (define-module (gnu packages racket) ;; ;; So, we build CGC to build 3M to build bootfiles and CS. ;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; ;; One remaining bootstrapping limitation is that Racket's reader, module ;; system, and macro expander are implemented in Racket. For Racket CS, ;; they are compiled to R6RS libraries as discussed above. This note from the @@ -145,14 +233,15 @@ (define (racket-vm-common-configure-flags) '())) ,@(cond ((false-if-exception - (search-input-file %build-inputs "/bin/racket")) + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) => (lambda (racket) (list (string-append "--enable-racket=" racket)))) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" #$(file-append bash-minimal "/bin/sh")) - "--disable-strip")) + "--disable-strip" + "--enable-origtree")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -173,31 +262,25 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal-bc-cgc +(define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. (hidden-package (package - (name "racket-minimal-bc-cgc") + (name "racket-vm-cgc") (version %racket-version) (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants (native-inputs (list libtool)) ;; <- only for BC variants (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main ;; distribution. @@ -208,51 +291,72 @@ (define-public racket-minimal-bc-cgc (ice-9 regex) (guix build gnu-build-system) (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) (home-page "https://racket-lang.org") (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or @@ -262,32 +366,33 @@ (define maybe-release-catalog scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the Racket CS implementation. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-3m +(define-public racket-vm-bc (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") + (inherit racket-vm-cgc) + (name "racket-vm-bc") (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + (substitute-keyword-arguments (package-arguments racket-vm-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") + (synopsis "Racket BC [3M] implementation") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'').") @@ -295,23 +400,23 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat)))) -(define-public racket-minimal +(define-public racket-vm-cs (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal") + (inherit racket-vm-bc) + (name "racket-vm-cs") (inputs - (modify-inputs (package-inputs racket-minimal-bc-cgc) + (modify-inputs (package-inputs racket-vm-cgc) (prepend zlib lz4) (delete "libffi"))) (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m))) + racket-vm-bc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:phases bc-phases) - #~(modify-phases #$bc-phases + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" @@ -328,17 +433,14 @@ (define-public racket-minimal "--enable-libz" "--enable-lz4" #$(racket-vm-common-configure-flags))))) - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") - (properties `()) +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) @@ -353,7 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source %racket-origin) (inputs `()) - (native-inputs (list racket-minimal-bc-3m)) + (native-inputs (list racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -371,7 +473,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) - "/bin/racket") + "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, @@ -452,10 +554,116 @@ (define (simple-racket-origin repo hash spec0 . spec*) spec0 spec*)) +(define-public racket-minimal + (package + (name "racket-minimal") + (version %racket-version) + (source #f) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs + (list openssl + sqlite + racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-packages-origin + "base" %racket-origin + '("base" "pkgs/base") + '("racket-lib" "pkgs/racket-lib")))) + (build-system gnu-build-system) + (arguments + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `configure-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install`. + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format + #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$configure-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. + +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + (define-public racket (package + (inherit racket-minimal) (name "racket") - (version %racket-version) (source #f) (inputs (list @@ -474,6 +682,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer + racket-vm-cs ;; TODO (racket-vm-for-system) (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") "2d" "2d-doc" "2d-lib") @@ -482,8 +691,6 @@ (define-public racket '("algol60" ".")) (racket-packages-origin "racket" %racket-origin - '("base" "pkgs/base") ;; FIXME belongs in racket-minimal - '("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal '("at-exp-lib" "pkgs/at-exp-lib") '("compiler" "pkgs/compiler") '("compiler-lib" "pkgs/compiler-lib") @@ -808,91 +1015,39 @@ (define-public racket "xrepl" "xrepl-doc" "xrepl-lib"))) (build-system gnu-build-system) (arguments - ;; We're using #:configure-flags to pass flags for - ;; `configure-layer.rkt` and #:make-flags to pass arguments for - ;; `raco pkg install`. - (list - #:configure-flags - #~`("--extra-foreign-lib-search-dirs" - ,(format #f "~s" - '(#$@(map (lambda (name) - (cond - ((this-package-input name) - => (cut file-append <> "/lib")) - (else - (raise-exception - (make-exception - (make-assertion-failure) - (make-exception-with-message - "missing input to the 'racket' package") - (make-exception-with-irritants - (list name))))))) - '("cairo" - "fontconfig-minimal" ;; aka fontconfig - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg-turbo" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))))) - #:make-flags #~`("main-distribution") - #:tests? #f ;; packaged separately - #:modules '((guix build gnu-build-system) - (guix build utils) - (guix build union) - (ice-9 match)) - #:imported-modules `((guix build union) - ,@%gnu-build-system-modules) - #:phases - #~(modify-phases %standard-phases - (delete 'unpack) - (replace 'configure - (lambda* (#:key inputs configure-flags #:allow-other-keys) - (let* ((racket (search-input-file inputs "bin/racket"))) - (apply invoke - racket - #$configure-layer.rkt - `(,@configure-flags - ,(dirname (dirname racket)) - ,#$output)) - (invoke racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" "setup" - "--no-user")))) - (replace 'build - (lambda* (#:key inputs #:allow-other-keys) - ;; We use "share/racket/pkgs" for sources to distinguish them - ;; from the "lib/racket/pkgs" of a potential parent layer. - (union-build (string-append #$output "/lib/racket/pkgs") - (search-path-as-list '("share/racket/pkgs") - (map cdr inputs)) - #:create-all-directories? #t))) - (replace 'install - (lambda* (#:key inputs make-flags #:allow-other-keys) - (let ((racket (search-input-file inputs "/bin/racket"))) - (unless (null? make-flags) - (invoke racket - "-l-" - "pkg/dirs-catalog" - "--link" - "local-catalog" - (string-append #$output "/lib/racket/pkgs")) - (apply invoke - racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" - "pkg" "install" - "--installation" - "--auto" - "--catalog" "local-catalog" - make-flags)))))))) - (home-page "https://racket-lang.org") + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -902,10 +1057,7 @@ (define-public racket The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) (define configure-layer.rkt (scheme-file @@ -918,41 +1070,53 @@ (define configure-layer.rkt racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define tethered? #f) + (define parent #f) (define extra-foreign-lib-search-dirs '()) - (define-values [parent-layer prefix] + (define-values [vm-dir prefix] (command-line #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] [("--extra-foreign-lib-search-dirs") dir-list "foreign library directories, as a list of strings in `read` syntax" (set! extra-foreign-lib-search-dirs (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (values parent-layer prefix))) + #:args (vm-dir prefix) + (values vm-dir prefix))) (let* ([config (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) (hash-set* config main-key @@ -961,7 +1125,10 @@ (define-values [parent-layer prefix] (list* #f (hash-ref config main-key - (build-path-string parent-layer pth)) + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) (filter values (hash-ref config search-key null)))))] [config (hash-update config @@ -995,15 +1162,21 @@ (define-values [rkt old-foreign-dirs] ;; workaround Guile reader/printer: ['|3m| "-bc"] [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) (make-parent-directory* new-config-pth) (call-with-output-file* new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez). 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (9 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath ` (12 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (chez-scheme-for-racket-bootstrap-bootfiles): Move to ... * gnu/packages/chez.scm (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable. [source]: Avoid problematic cycle with "racket.scm". [arguments]<#:phases>: Likewise. --- gnu/packages/chez.scm | 62 +++++++++++++++++++++++++++++++++++++++++ gnu/packages/racket.scm | 52 ---------------------------------- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..046bb3dcdc 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -31,12 +31,14 @@ (define-module (gnu packages chez) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) #:use-module (gnu packages linux) #:use-module (gnu packages netpbm) + #:use-module (gnu packages racket) #:use-module (gnu packages tex) #:use-module (gnu packages compression) #:use-module (gnu packages image) @@ -260,6 +262,66 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs `()) + (native-inputs (list racket-vm-bc)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(let ((unpack (assoc-ref %standard-phases 'unpack))) + (modify-phases %standard-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + (copy-recursively + #$nanopass + "nanopass" + #:keep-mtime? #t))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme.") + (license (list asl2.0)))) + (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 3271e78d45..59944031e6 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -445,58 +445,6 @@ (define-public racket-vm-cs ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) -(define-public chez-scheme-for-racket-bootstrap-bootfiles - (package - (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (source %racket-origin) - (inputs `()) - (native-inputs (list racket-vm-bc)) - (build-system copy-build-system) - ;; TODO: cross compilation - (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(modify-phases %standard-phases - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$(make-unpack-nanopass+stex))) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt")))))) - (home-page "https://github.com/racket/ChezScheme") - ;; ^ This is downstream of https://github.com/racket/racket, - ;; but it's designed to be a friendly landing place for people - ;; who want a ChezScheme-shaped repositroy. - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list license:asl2.0)))) - (define (racket-packages-origin name origin spec0 . spec*) "Extract from ORIGIN the sources for the Racket packages specified by SPEC0 and any additional arguments SPEC*. In the resulting file-like object, each -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 12/24] gnu: chez: Add utilities for Chez machine types. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (10 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath ` (11 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. (chez-scheme-for-racket-bootstrap-bootfiles)[supported-systems]: Compute based on 'nix-system->chez-machine'. --- gnu/packages/chez.scm | 127 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 046bb3dcdc..603fc4201e 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -44,7 +44,119 @@ (define-module (gnu packages chez) #:use-module (gnu packages image) #:use-module (gnu packages xorg) #:use-module (ice-9 match) - #:use-module (srfi srfi-1)) + #:use-module (srfi srfi-1) + #:export (nix-system->chez-machine + chez-machine->nonthreaded + chez-machine->threaded)) + +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; (define nanopass (let ((version "1.9.2")) @@ -251,8 +363,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description @@ -300,6 +415,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people @@ -322,6 +439,10 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Chez Scheme.") (license (list asl2.0)))) +;; +;; Packages: +;; + (define-public chez-srfi (package (name "chez-srfi") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 13/24] gnu: racket: Add 'racket-vm-for-system'. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (11 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath ` (10 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-vm-for-system): New procedure. (racket-minimal, racket)[inputs]: Use it. --- gnu/packages/racket.scm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 59944031e6..10ec0591d9 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -187,6 +187,14 @@ (define-module (gnu packages racket) ;; ;; Code: +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define %racket-version "8.4") ;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit @@ -513,7 +521,7 @@ (define-public racket-minimal (inputs (list openssl sqlite - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (racket-packages-origin "base" %racket-origin '("base" "pkgs/base") @@ -630,7 +638,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") "2d" "2d-doc" "2d-lib") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 14/24] gnu: chez-scheme: Use new style for Chez packages. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (12 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (9 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-configure, chez-make-flags): Use G-expressions. (chez-srfi)[arguments]: Use G-expressions, 'chez-configure', and 'chez-make-flags'. (chez-web, chez-sockets)[native-inputs]: Remove labels. [arguments]: Use G-expressions. (chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils)[arguments]: Use G-expressions. --- gnu/packages/chez.scm | 382 ++++++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 186 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 603fc4201e..4ee9711bb4 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -443,6 +443,27 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; Packages: ;; +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'chezversion' so that libraries are installed in + ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. + (string-append "chezversion=" #$(package-version chez-scheme)) + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -460,13 +481,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -491,42 +510,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -550,95 +575,78 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/csv" + (package-version chez-scheme) "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/csv" + #$(package-version chez-scheme) + "-site/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -659,10 +667,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -690,10 +699,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -720,17 +730,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -760,10 +771,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -792,46 +804,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) - (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) - (with-directory-excursion (dirname mk-file) - (apply invoke "make" "build" make-flags))))) - (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) + (add-after 'absolute-path-in-scm-files 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) + (with-directory-excursion (dirname mk-file) + (apply invoke "make" "build" make-flags))))) + (add-after 'build 'clean-up + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (13 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 8:48 ` Liliana Marie Prikler 2022-02-27 2:34 ` [bug#53878] [PATCH v6 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (8 subsequent siblings) 23 siblings, 1 reply; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". (chez-make-flags): Update accordingly. (chez-sockets)[arguments]<#:phases>: Likewise. --- gnu/packages/chez.scm | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 4ee9711bb4..f4c87fbcf7 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -233,7 +233,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files '("lib/chez-scheme"))))) (outputs '("out" "doc")) (arguments `(#:modules @@ -458,9 +458,9 @@ (define chez-configure (define (chez-make-flags name version) #~(let ((out #$output)) (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" #$(package-version chez-scheme)) + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") (string-append "PREFIX=" out) (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) @@ -608,9 +608,7 @@ (define-public chez-sockets (replace 'build (lambda args (let ((chez-site (string-append #$output - "/lib/csv" - (package-version chez-scheme) - "-site/arcfide"))) + "/lib/chez-scheme/arcfide"))) ;; make sure Chez Scheme can find the shared libraries. (substitute* "sockets.ss" (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" @@ -634,9 +632,7 @@ (define-public chez-sockets (lambda args (install-file "sockets.so" (string-append #$output - "/lib/csv" - #$(package-version chez-scheme) - "-site/arcfide")) + "/lib/chez-scheme/arcfide")) (install-file "sockets.pdf" (string-append #$output "/share/doc/" -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-27 8:48 ` Liliana Marie Prikler 0 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-02-27 8:48 UTC (permalink / raw) To: Philip McGrath, 53878, zimoun Cc: Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Am Samstag, dem 26.02.2022 um 21:34 -0500 schrieb Philip McGrath: > There does not seem to be any widely accepted standard path to use > for "CHEZSCHEMELIBDIRS". Using a path without a version number in it > avoids having to compute the actual path everywhere, which would be > especially unpleasant when support is added for the Racket variant of > Chez Scheme, which always has a different version number than > upstream. > > * gnu/packages/chez.scm (chez-scheme)[native-search-paths]: Change to > use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for > "CHEZSCHEMELIBDIRS". > (chez-make-flags): Update accordingly. > (chez-sockets)[arguments]<#:phases>: Likewise. Having separated this from cosmetic changes makes it much easier to review, thanks. LGTM ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 16/24] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (14 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 17/24] gnu: chez-scheme: Use new package style Philip McGrath ` (7 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index f4c87fbcf7..dd40baa719 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -211,9 +211,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -266,14 +264,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 17/24] gnu: chez-scheme: Use new package style. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (15 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 18/24] gnu: Add stex Philip McGrath ` (6 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove labels. [native-inputs]: Likewise. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass): Make public as a temporary workaround for Racket. * gnu/packages/racket.scm (make-unpack-nanopass+stex): Update accordingly. --- gnu/packages/chez.scm | 286 +++++++++++++++++++--------------------- gnu/packages/racket.scm | 5 +- 2 files changed, 135 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index dd40baa719..ad263a8fe3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -158,7 +158,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -185,86 +185,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files '("lib/chez-scheme"))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -272,90 +266,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 10ec0591d9..73de273c64 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -257,10 +257,7 @@ (define (make-unpack-nanopass+stex) ;; TODO: Refactor enough to share this directly. #~(begin (copy-recursively - #$(match (assoc-ref (package-native-inputs chez-scheme) - "nanopass") - ((src) - src)) + #$nanopass "nanopass" #:keep-mtime? #t) (mkdir-p "stex") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 18/24] gnu: Add stex. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (16 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 17/24] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 19/24] gnu: Add chez-nanopass Philip McGrath ` (5 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap' (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. --- gnu/packages/chez.scm | 217 ++++++++++++++++++++++++++++++------------ 1 file changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index ad263a8fe3..6855195cfe 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -33,6 +33,7 @@ (define-module (gnu packages chez) #:use-module (guix gexp) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) + #:use-module (guix build-system copy) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) @@ -158,30 +159,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -218,15 +195,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -249,9 +218,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -287,32 +258,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -320,7 +268,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -420,7 +370,150 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (license (list asl2.0)))) ;; -;; Packages: +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +;; +;; Other Chez packages: ;; ;; Help function for Chez Scheme to add the current path to -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 19/24] gnu: Add chez-nanopass. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (17 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 18/24] gnu: Add stex Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (4 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-nanopass): New variable. (unpack-nanopass+stex): New variable using 'chez-nanopass-bootstrap'. (chez-scheme-for-racket-bootstrap-bootfiles, chez-scheme)[native-inputs]: Add 'chez-nanopass-bootstrap'. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. * gnu/packages/racket.scm (racket-vm-cs): Likewise. (make-unpack-nanopass+stex): Remove it. --- gnu/packages/chez.scm | 122 +++++++++++++++++++++++++++++++--------- gnu/packages/racket.scm | 19 +------ 2 files changed, 98 insertions(+), 43 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 6855195cfe..43d2c764f3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -48,7 +48,8 @@ (define-module (gnu packages chez) #:use-module (srfi srfi-1) #:export (nix-system->chez-machine chez-machine->nonthreaded - chez-machine->threaded)) + chez-machine->threaded + unpack-nanopass+stex)) (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string @@ -159,6 +160,20 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; + +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + (define-public chez-scheme (package (name "chez-scheme") @@ -176,6 +191,9 @@ (define-public chez-scheme (file-name (git-file-name name version)) (snippet #~(begin (use-modules (guix build utils)) + ;; TODO: consider putting this in a (guix ...) or + ;; (guix build ...) module so it can be shared + ;; with the Racket origin without cyclic issues. (for-each (lambda (dir) (when (directory-exists? dir) (delete-file-recursively dir))) @@ -193,9 +211,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -215,14 +231,7 @@ (define-public chez-scheme #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + #$unpack-nanopass+stex)) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -317,7 +326,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm (inputs `()) - (native-inputs (list racket-vm-bc)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -336,10 +345,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (chdir "racket/src/ChezScheme"))) (add-after 'chdir 'unpack-nanopass+stex (lambda args - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t))) + #$unpack-nanopass+stex)) (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) @@ -502,15 +508,79 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) ;; ;; Other Chez packages: diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 73de273c64..c96bebe325 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -251,22 +251,6 @@ (define (racket-vm-common-configure-flags) "--disable-strip" "--enable-origtree")) -(define (make-unpack-nanopass+stex) - ;; Adapted from chez-scheme. - ;; Thunked to avoid evaluating 'chez-scheme' too early. - ;; TODO: Refactor enough to share this directly. - #~(begin - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) - - (define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. @@ -417,6 +401,7 @@ (define-public racket-vm-cs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles + chez-nanopass-bootstrap racket-vm-bc))) (arguments (substitute-keyword-arguments (package-arguments racket-vm-cgc) @@ -425,7 +410,7 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) + #$unpack-nanopass+stex))) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (with-directory-excursion "racket/src/ChezScheme" -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (18 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 19/24] gnu: Add chez-nanopass Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (3 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. (chez-scheme-for-racket-bootstrap-bootfiles): Inherit from 'chez-scheme-bootstrap-bootfiles'. [arguments]: Adapt accordingly. --- gnu/packages/chez.scm | 98 +++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 43d2c764f3..da267d3616 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -46,6 +46,7 @@ (define-module (gnu packages chez) #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded @@ -211,7 +212,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -232,6 +235,14 @@ (define-public chez-scheme (add-after 'unpack 'unpack-nanopass+stex (lambda args #$unpack-nanopass+stex)) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -316,8 +327,46 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + (define-public chez-scheme-for-racket-bootstrap-bootfiles (package + (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") (version "9.5.7.3") ;; The version should match `(scheme-fork-version-number)`. @@ -325,32 +374,30 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; It will always be different than the upstream version! ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm - (inputs `()) (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) - (build-system copy-build-system) ;; TODO: cross compilation (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(let ((unpack (assoc-ref %standard-phases 'unpack))) - (modify-phases %standard-phases - (replace 'unpack - (lambda args - (unpack #:source #$(or (package-source this-package) - (package-source racket-vm-bc))))) - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$unpack-nanopass+stex)) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt"))))))) + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt")))))))) (supported-systems (filter nix-system->chez-machine %supported-systems)) (home-page "https://github.com/racket/ChezScheme") @@ -372,8 +419,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0)))) +Chez Scheme."))) ;; ;; Chez's bootstrap dependencies: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 21/24] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (19 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 22/24] gnu: Add chez-scheme-for-racket Philip McGrath ` (2 subsequent siblings) 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index da267d3616..5d5108a2b1 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -949,7 +949,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 22/24] gnu: Add chez-scheme-for-racket. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (20 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez.scm (chez-scheme-for-racket): New variable. (chez-scheme-for-racket-bootstrap-bootfiles)[version, supported-systems]: Derive from 'chez-scheme-for-racket'. * gnu/packages/racket.scm (%racket-version): Update comment. --- gnu/packages/chez.scm | 97 ++++++++++++++++++++++++++++++++++++++--- gnu/packages/racket.scm | 3 +- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 5d5108a2b1..e7ddab0d1f 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -52,6 +52,21 @@ (define-module (gnu packages chez) chez-machine->threaded unpack-nanopass+stex)) +;; Commentary: +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Code: + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -327,6 +342,78 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme")))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license asl2.0))) + +;; +;; Bootfiles: +;; + (define-public chez-scheme-bootstrap-bootfiles (package (inherit chez-scheme) @@ -368,11 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (package (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. + (version (package-version chez-scheme-for-racket)) (source #f) ; avoid problematic cycle with racket.scm (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) ;; TODO: cross compilation @@ -398,8 +481,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))))) - (supported-systems (filter nix-system->chez-machine - %supported-systems)) + (supported-systems + (package-supported-systems chez-scheme-for-racket)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index c96bebe325..98dab6f743 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -195,8 +195,7 @@ (define* (racket-vm-for-system #:optional racket-vm-cs racket-vm-bc)) -(define %racket-version "8.4") -;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! +(define %racket-version "8.4") ; Remember to update chez-scheme-for-racket! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 23/24] gnu: chez: Add 'chez-scheme-for-system'. 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (21 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 22/24] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-scheme-for-system): New procedure. (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Use 'chez-scheme-for-system'. * gnu/packages/loko.scm (loko-scheme): Likewise. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise --- gnu/packages/chez.scm | 33 ++++++++++++++++++++++++--------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index e7ddab0d1f..b3aadf3a78 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -47,7 +47,8 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) - #:export (nix-system->chez-machine + #:export (chez-scheme-for-system + nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded unpack-nanopass+stex)) @@ -67,6 +68,20 @@ (define-module (gnu packages chez) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (or + ;; full support upstream + (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)) + ;; no support anywhere + (not (nix-system->chez-machine system))) + chez-scheme + chez-scheme-for-racket)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -751,7 +766,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -782,7 +797,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -847,7 +862,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -933,7 +948,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -965,7 +980,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -996,7 +1011,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -1059,7 +1074,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -1090,7 +1105,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index ef98088100..df53df61c7 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..449c62f1f0 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v6 24/24] gnu: racket-vm-cs: Build with "--enable-scheme". 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath ` (22 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-27 2:34 ` Philip McGrath 23 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 2:34 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-vm-cs)[native-inputs]: Remove 'chez-scheme-for-racket-bootstrap-bootfiles'. Add 'chez-scheme-for-racket'. [arguments]<#:phases>: Delete 'unpack-bootfiles'. <#:configure-flags>: Add "--enable-scheme". --- gnu/packages/racket.scm | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 98dab6f743..952bec6aa9 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -399,7 +399,7 @@ (define-public racket-vm-cs (native-inputs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") - (prepend chez-scheme-for-racket-bootstrap-bootfiles + (prepend chez-scheme-for-racket chez-nanopass-bootstrap racket-vm-bc))) (arguments @@ -409,18 +409,15 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$unpack-nanopass+stex))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))))) + #$unpack-nanopass+stex))))) ((#:configure-flags _ '()) #~(cons* "--enable-csonly" "--enable-libz" "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") #$(racket-vm-common-configure-flags))))) (synopsis "Racket CS implementation") (description "The Racket CS implementation, which uses ``Chez Scheme'' as -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (16 preceding siblings ...) 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath @ 2022-02-27 21:28 ` Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath ` (24 more replies) 17 siblings, 25 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:28 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Hi, On Sunday, February 27, 2022 3:42:46 AM EST Liliana Marie Prikler wrote: > > Perhaps I wasn't clear enough about this in v5, but I think spec should > be a single argument rather than multiple ones. This way, if we do > find that we need to extend it to support an additional argument, we > don't have to awkwardly code around the #:rest. > Rather than debate it, I'm sending a v7 with the change to patch 03/24 that Liliana requested in <https://issues.guix.gnu.org/53878#187>. In the medium term, I'd rather put effort into making a `racket-build-system` than tinker too much with the current way of doing things. -Philip Philip McGrath (24): gnu: Use license prefix in (gnu packages racket). gnu: racket: Update to 8.4. gnu: racket: Use Git origins for Racket packages. gnu: racket-minimal: Use new package style. gnu: racket-minimal: Don't configure non-existant catalogs. gnu: racket-minimal: Change inheritance to follow bootstrapping. gnu: racket-minimal: Adjust indentation. gnu: racket-minimal: Add "debug" output. gnu: configure-layer.rkt: Adjust indentation. gnu: racket-minimal: Separate from the Racket VM. gnu: racket: Move Chez bootfiles to (gnu packages chez). gnu: chez: Add utilities for Chez machine types. gnu: racket: Add 'racket-vm-for-system'. gnu: chez-scheme: Use new style for Chez packages. gnu: chez-scheme: Use "lib/chez-scheme" for search path. gnu: chez-scheme: Use shared zlib and lz4. gnu: chez-scheme: Use new package style. gnu: Add stex. gnu: Add chez-nanopass. gnu: chez-scheme: Explicitly package bootstrap bootfiles. gnu: chez-mit: Support chez-scheme-for-racket. gnu: Add chez-scheme-for-racket. gnu: chez: Add 'chez-scheme-for-system'. gnu: racket-vm-cs: Build with "--enable-scheme". gnu/local.mk | 4 +- gnu/packages/chez.scm | 1264 ++++++++++----- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- .../racket-enable-scheme-backport.patch | 465 ++++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 1433 +++++++++++------ 7 files changed, 2342 insertions(+), 854 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch -- 2.32.0 ^ permalink raw reply [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 01/24] gnu: Use license prefix in (gnu packages racket). 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath @ 2022-02-27 21:28 ` Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 02/24] gnu: racket: Update to 8.4 Philip McGrath ` (23 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:28 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal, racket-minimal-bc-3m, racket-bootstrap-chez-bootfiles): Use license prefix. --- gnu/packages/racket.scm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d0a5ca494b..ec9e836a4c 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -21,8 +21,6 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu packages racket) - #:use-module ((guix licenses) - #:select (asl2.0 expat lgpl3+)) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) @@ -47,7 +45,8 @@ (define-module (gnu packages racket) #:use-module (gnu packages multiprecision) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) - #:use-module (gnu packages xorg)) + #:use-module (gnu packages xorg) + #:use-module ((guix licenses) #:prefix license:)) ;; Commentary: ;; @@ -254,7 +253,7 @@ (define (write-racket-hash alist) DrRacket IDE, are not included.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list asl2.0 expat)))) + (license (list license:asl2.0 license:expat)))) (define-public racket-minimal-bc-3m @@ -295,7 +294,7 @@ (define-public racket-minimal-bc-3m collector, 3M (``Moving Memory Manager'').") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list lgpl3+ asl2.0 expat))))) + (license (list license:lgpl3+ license:asl2.0 license:expat))))) (define-public racket-minimal-bc-cgc @@ -372,7 +371,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list asl2.0))))) + (license (list license:asl2.0))))) (define %installer-mirrors -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 02/24] gnu: racket: Update to 8.4. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath @ 2022-02-27 21:28 ` Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath ` (22 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:28 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-enable-scheme-backport.patch, gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: New patches. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/racket.scm (%racket-version): New variable. (%racket-commit): New variable. (%racket-origin): New variable. [patches]: Add "racket-enable-scheme-backport.patch". (racket-minimal): Update to 8.4. [version]: Use '%racket-version'. [source]: Use '%racket-origin'. [inputs]: Add 'ncurses'. Remove 'zlib:static' and 'lz4:static'. (racket-minimal-bc-3m)[inputs]: Adjust accordingly. (racket-bootstrap-chez-bootfiles)[version]: Use Chez Scheme's '(scheme-fork-version-number)'. (racket)[version]: Use '%racket-version'. [native-inputs]: Use '%racket-origin'. [source]: Update to 8.4. <patches>: Use "racket-gui-tethered-launcher-backport.patch". <snippet>: Remove "srfi-doc-nonfree". --- gnu/local.mk | 4 +- .../racket-enable-scheme-backport.patch | 465 ++++++++++++++++++ ...acket-gui-tethered-launcher-backport.patch | 26 + gnu/packages/racket.scm | 99 ++-- 4 files changed, 557 insertions(+), 37 deletions(-) create mode 100644 gnu/packages/patches/racket-enable-scheme-backport.patch create mode 100644 gnu/packages/patches/racket-gui-tethered-launcher-backport.patch diff --git a/gnu/local.mk b/gnu/local.mk index 98f2d4ac30..cf34905431 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -41,7 +41,7 @@ # Copyright © 2020 Vinicius Monego <monego@posteo.net> # Copyright © 2021 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> # Copyright © 2021 Greg Hogan <code@greghogan.com> -# Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +# Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> # Copyright © 2021 Arun Isaac <arunisaac@systemreboot.net> # Copyright © 2021 Sharlatan Hellseher <sharlatanus@gmail.com> # Copyright © 2021 Dmitry Polyakov <polyakov@liltechdude.xyz> @@ -1749,6 +1749,8 @@ dist_patch_DATA = \ %D%/packages/patches/ripperx-missing-file.patch \ %D%/packages/patches/rpcbind-CVE-2017-8779.patch \ %D%/packages/patches/rtags-separate-rct.patch \ + %D%/packages/patches/racket-enable-scheme-backport.patch \ + %D%/packages/patches/racket-gui-tethered-launcher-backport.patch \ %D%/packages/patches/racket-minimal-sh-via-rktio.patch \ %D%/packages/patches/remake-impure-dirs.patch \ %D%/packages/patches/restic-0.9.6-fix-tests-for-go1.15.patch \ diff --git a/gnu/packages/patches/racket-enable-scheme-backport.patch b/gnu/packages/patches/racket-enable-scheme-backport.patch new file mode 100644 index 0000000000..3a5a4a3d82 --- /dev/null +++ b/gnu/packages/patches/racket-enable-scheme-backport.patch @@ -0,0 +1,465 @@ +From 8d7687842f099e3e7e60d3a83fed58b2c6a92863 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 10:36:09 -0700 +Subject: [PATCH 1/2] Chez Scheme: adapt bootfile build for supplied `Scheme=` + +(cherry picked from commit fca1e02349664060e10278ca2ce6577a949bebf5) + +(Fixed conflicts by dropping pbchunks and pbarch changes.) +--- + racket/src/ChezScheme/configure | 15 ++++++++++++++- + racket/src/ChezScheme/s/Mf-base | 4 ++-- + racket/src/ChezScheme/s/Mf-cross | 4 +++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/racket/src/ChezScheme/configure b/racket/src/ChezScheme/configure +index 4515ffc105..0098829091 100755 +--- a/racket/src/ChezScheme/configure ++++ b/racket/src/ChezScheme/configure +@@ -45,6 +45,7 @@ threads=yes + nothreads=no + temproot="" + help=no ++forceworkarea=no + gzipmanpages=yes + installowner="" + installgroup="" +@@ -205,6 +206,9 @@ while [ $# != 0 ] ; do + --pb) + pb=yes + ;; ++ --force) ++ forceworkarea=yes ++ ;; + --installprefix=*) + installprefix=`echo $1 | sed -e 's/^--installprefix=//'` + ;; +@@ -439,6 +443,7 @@ if [ "$help" = "yes" ]; then + echo " --toolprefix=<prefix> prefix tool (compiler, linker, ...) names" + echo " --[no]gzip-man-pages compress manual pages ($gzipmanpages)" + echo " --workarea=<pathname> build directory ($w)" ++ echo " --force configure even without boot files" + echo " CC=<C compiler> C compiler" + echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags" + echo " CFLAGS=<C compiler flags> C compiler flags" +@@ -721,8 +726,16 @@ case "${flagsmuni}" in + ;; + esac + ++if [ "$w" = "$m" ] ; then ++ configuringin="" ++else ++ configuringin=" in $w" ++fi ++ + if [ -f boot/$m/scheme.boot -o -f "$srcdir"/boot/$m/scheme.boot ] ; then +- echo "Configuring for $m" ++ echo "Configuring for $m$configuringin" ++elif [ "$forceworkarea" = yes ] ; then ++ echo "Configuring for $m$configuringin despite missing boot files" + else + if [ "$m" = "" ] ; then + maybem="<machine type>" +diff --git a/racket/src/ChezScheme/s/Mf-base b/racket/src/ChezScheme/s/Mf-base +index cc6178c973..1f4a967998 100644 +--- a/racket/src/ChezScheme/s/Mf-base ++++ b/racket/src/ChezScheme/s/Mf-base +@@ -94,7 +94,7 @@ endif + # that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme + # implementation + Scheme = ../bin/$m/scheme${ExeSuffix} +-export SCHEMEHEAPDIRS=../boot/%m ++export SCHEMEHEAPDIRS=../boot/$m + export CHEZSCHEMELIBDIRS=. + + # Define the libdirs separator character +@@ -691,4 +691,4 @@ reset-one: + + .PHONY: run + run: +- env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS) ++ env SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} ${Scheme} $(ARGS) +diff --git a/racket/src/ChezScheme/s/Mf-cross b/racket/src/ChezScheme/s/Mf-cross +index d796cbb459..397af59a28 100644 +--- a/racket/src/ChezScheme/s/Mf-cross ++++ b/racket/src/ChezScheme/s/Mf-cross +@@ -43,5 +43,7 @@ x$(xm).$(m): + $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch + mv xpatch x$(xm).$(m) + ++ifneq ($(SCHEMEHEAPDIRS),:) + # Ensure that cross-compiling "nanopass.so" is rebuilt if the host compiler changed +-nanopass.so: ${SCHEME} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++nanopass.so: ${Scheme} ${SCHEMEHEAPDIRS}/petite.boot ${SCHEMEHEAPDIRS}/scheme.boot ++endif +-- +2.32.0 + + +From 26c8e2c1d9b02ad85acef8bda40d92154cf0b699 Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Sun, 6 Feb 2022 11:03:30 -0700 +Subject: [PATCH 2/2] configure: make `--enable-scheme` work with an executable + +When the same Chez Scheme version as used by Racket is already +available, then `--enable-scheme=...` can supply an executable. For +cross builds, `--enable-scheme=...` can still supply a build +directory, instead, as before. + +(cherry picked from commit 4f0e76855ce7e86107de495292a553469daf0b3f) +--- + racket/src/ChezScheme/makefiles/Makefile.in | 3 ++ + racket/src/README.txt | 30 +++++++++++--- + racket/src/configure | 8 +++- + racket/src/cs/README.txt | 6 ++- + racket/src/cs/c/Makefile.in | 44 ++++++++++++++++----- + racket/src/cs/c/configure | 24 +++++++++-- + racket/src/cs/c/configure.ac | 21 ++++++++-- + 7 files changed, 112 insertions(+), 24 deletions(-) + +diff --git a/racket/src/ChezScheme/makefiles/Makefile.in b/racket/src/ChezScheme/makefiles/Makefile.in +index c396efc851..3998ef9ccd 100644 +--- a/racket/src/ChezScheme/makefiles/Makefile.in ++++ b/racket/src/ChezScheme/makefiles/Makefile.in +@@ -59,6 +59,9 @@ reset: + %.boot: + (cd $(workarea) && $(MAKE) $*.boot) + ++auto.boot: ++ (cd $(workarea) && $(MAKE) $(defaultm).boot) ++ + # <machine>.bootquick to build boot files for <machine> + # with o=3 d=0 for the cross compiler, and only after + # building the kernel for the configured machine +diff --git a/racket/src/README.txt b/racket/src/README.txt +index 98647aebce..d77310b4a4 100644 +--- a/racket/src/README.txt ++++ b/racket/src/README.txt +@@ -354,6 +354,10 @@ variant of MinGW without "libdelayimp.a", get the implementation of + ======================================================================== + + Cross-compilation requires at least two flags to `configure`: ++`--host=OS` and either `--enable-racket=RACKET` or (for Racket CS) ++`--enable-scheme-SCHEME`. ++ ++More information: + + * `--host=OS`, where OS is something like `i386-gnu-linux` to + indicate the target platform. +@@ -374,11 +378,27 @@ Cross-compilation requires at least two flags to `configure`: + run `configure` again (with no arguments) in a "local" subdirectory + to create a build for the current platform. + +-An additional flag is needed for building Racket CS, unless the flag +-`--enable-racket=auto` is used: +- +- * `--enable-scheme=DIR`, where DIR is a path that has a "ChezScheme" +- directory where Chez Scheme is built for the host system. ++ * `--enable-scheme=SCHEME`, where SCHEME is a Chez Scheme executable ++ executable that runs on the build platform; the executable must be ++ the same version as used in Racket built for the target platform. ++ ++ Supplying `--enable-scheme=DIR` is also supported in cross-build ++ mode, where DIR is a path that has a "ChezScheme" directory where ++ Chez Scheme is built for the host system. ++ ++The `--enable-racket=RACKET` and `--enable-scheme=SCHEME` flags are ++allowed for non-cross builds, too: ++ ++ * For Racket CS, supplying either selects a Racket or Chez Scheme ++ implementation used to create boot files to the build platform. ++ Suppling Chez Scheme is a much more direct path, but when Racket is ++ supplied, its version does not have to match the version being ++ built. ++ ++ * For Racket BC, `--enable-racket=RACKET` selects a Racket for ++ prepare C sources to cooperate with garbage collection. Its version ++ needs to be close to the one being built, and potentially exactly ++ the same version. + + Some less commonly needed `configure` flags are for Racket BC: + +diff --git a/racket/src/configure b/racket/src/configure +index c9f3ba4419..1b53ec7ce2 100755 +--- a/racket/src/configure ++++ b/racket/src/configure +@@ -9,6 +9,7 @@ pb_dir="$dir/ChezScheme/boot/pb" + use_cs=maybe + use_bc=maybe + supplied_racket=no ++supplied_scheme=no + enable_boothelp= + + # We don't have to detect conflicts like `--enable-csdefault --enable-bcdefault`, +@@ -34,6 +35,9 @@ for arg in $*; do + --enable-racket=*) + supplied_racket=yes + ;; ++ --enable-scheme=*) ++ supplied_scheme=yes ++ ;; + --help | -h) + echo $0: + echo see --help-bc or --help-cs, since the Racket CS build and the +@@ -70,8 +74,8 @@ elif test "$use_cs" = "maybe" ; then + fi + + if test "$use_cs" = "yes" ; then +- if test $use_bc = no -a $supplied_racket = no -a ! -d "$pb_dir" ; then +- echo $0: must have $pb_dir or --enable-racket=... for --enable-csonly ++ if test $use_bc = no -a $supplied_racket = no -a $supplied_scheme = no -a ! -d "$pb_dir" ; then ++ echo $0: must have $pb_dir, --enable-racket=... or --enable-scheme=... for --enable-csonly + exit 1 + fi + +diff --git a/racket/src/cs/README.txt b/racket/src/cs/README.txt +index 2ece417b78..8e6fc57b74 100644 +--- a/racket/src/cs/README.txt ++++ b/racket/src/cs/README.txt +@@ -39,6 +39,11 @@ build: + installed in the "../ChezScheme/boot/pb" directory as described by + "../ChezScheme/BUILDING". + ++ Supplying `--enable-scheme=...` is also an option if you alerady ++ have the same version of Chez Scheme built on the current platform. ++ Another build will be created, anyway, but more quickly than ++ without Chez Scheme. ++ + * Racket is needed to generate the files in the "schemified" + directory from the sources in sibling directories like "../io". The + Racket version must be practically the same as the current Racket +@@ -48,7 +53,6 @@ build: + Unlike Chez Scheme boot files, the files generated in "schemified" + are human-readable and -editable Scheme code. That provides a way + out of bootstrapping black holes, even without BC. +- + + + ======================================================================== +diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in +index 54a644a1d9..d73993f0fc 100644 +--- a/racket/src/cs/c/Makefile.in ++++ b/racket/src/cs/c/Makefile.in +@@ -12,7 +12,9 @@ CS_HOST_WORKAREA_PREFIX = @CS_HOST_WORKAREA_PREFIX@ + SCHEME_HOST_WORKAREA = $(CS_HOST_WORKAREA_PREFIX)$(SCHEME_WORKAREA) + SCHEME_BIN = $(SCHEME_HOST_WORKAREA)/$(MACH)/bin/$(MACH)/scheme + SCHEME_INC = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH) +-SCHEME = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_built = $(SCHEME_BIN) -B $(SCHEME_INC)/petite.boot -B $(SCHEME_INC)/scheme.boot ++SCHEME_existing = @MAKE_SCHEME_SCHEME@ ++SCHEME = $(SCHEME@USE_SCHEME_MODE@) + + TARGET_MACH = @TARGET_MACH@ + SCHEME_TARGET_INC = $(SCHEME_WORKAREA)/$(TARGET_MACH)/boot/$(TARGET_MACH) +@@ -88,7 +90,7 @@ mainsrcdir = @srcdir@/../.. + @INCLUDEDEP@ @srcdir@/../../version/version.mak + + cs: +- $(MAKE) scheme@T_CROSS_MODE@ ++ $(MAKE) scheme@MAKE_SCHEME_MODE@ + $(MAKE) racket-so + cd rktio; $(MAKE) + $(MAKE) racketcs +@@ -121,9 +123,13 @@ racket-so: + + RACKET_SO_ENV = @CONFIGURE_RACKET_SO_COMPILE@ + ++TARGET_MACH_built = $(TARGET_MACH) ++TARGET_MACH_existing = xc-$(TARGET_MACH) ++XPATCH_FILE = $(SCHEME_WORKAREA)/$(TARGET_MACH@USE_SCHEME_MODE@)/s/xpatch ++ + CS_PROGS = SCHEME="$(SCHEME)" + CS_OPTS = COMPRESS_COMP=@COMPRESS_COMP@ @ENABLE_OR_DISABLE_WPO@ +-CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch" ++CS_OPTScross = $(CS_OPTS) CSO=$(MACH) CROSS_COMP="--xpatch $(XPATCH_FILE)" + PASS_COMPILE_DEPS = EXTRA_COMPILE_DEPS="$(SCHEME_INC)/petite.boot $(SCHEME_INC)/scheme.boot" + + build-racket-so: +@@ -163,6 +169,15 @@ pb-bootquick: + cd $(SCHEME_WORKAREA) && $(MAKE) reset + $(SHELL) $(srcdir)/ready_boot.sh $(MACH) $(SCHEME_WORKAREA) + ++scheme-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot ++ $(MAKE) mach-make ++ ++$(SCHEME_WORKAREA)/boot/$(MACH)/scheme.boot: ++ mkdir -p $(SCHEME_WORKAREA) ++ $(MAKE) config-scheme CONFIG_SCHEME_MODE="$(CONFIG_SCHEME_MODE) --force" ++ cd $(SCHEME_WORKAREA) && $(MAKE) $(MACH).boot Scheme="$(SCHEME)" SCHEMEHEAPDIRS=: o=3 d=0 what=all ++ + mach-make: + $(MAKE) config-scheme + cd $(SCHEME_WORKAREA) && $(MAKE) +@@ -182,24 +197,33 @@ config-scheme: + + scheme-cross: + env MAKE_BOOT_FOR_CROSS=yes SCHEME_SRC="$(SCHEME_DIR)" SCHEME_WORKAREA=$(SCHEME_WORKAREA) MACH="$(TARGET_MACH)" $(BOOTSTRAP_RACKET) "$(SCHEME_DIR)"/rktboot/make-boot.rkt ++ $(MAKE) finish-scheme-cross ++ ++finish-scheme-cross: + $(SHELL) $(srcdir)/reset_boot.sh $(TARGET_MACH) $(SCHEME_WORKAREA) + cd $(SCHEME_WORKAREA) && "$(UP_SCHEME_DIR)"/configure @SCHEME_CROSS_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/c && $(CHOST_HACK@T_CROSS_MODE@) $(MAKE) o=o cross=t +- $(MAKE) $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++ $(MAKE) $(XPATCH_FILE) ++ ++scheme-cross-via-scheme: ++ $(MAKE) $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot MACH=$(TARGET_MACH) ++ $(MAKE) finish-scheme-cross + + # Rebuild patch file and cross "petite.boot" and "scheme.boot" when older +-# than the build-host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files +-XPATCH_DEPS = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ +- $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++# than the build-<host "scheme.boot" or when "make-boot.rkt" touchs dummy boot files ++XPATCH_DEPS_built = $(SCHEME_HOST_WORKAREA)/$(MACH)/boot/$(MACH)/scheme.boot \ ++ $(SCHEME_WORKAREA)/boot/$(TARGET_MACH)/scheme.boot ++XPATCH_DEPS_existing = ++XPATCH_DEPS = $(XPATCH_DEPS@USE_SCHEME_MODE@) + +-$(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch: $(XPATCH_DEPS) ++$(XPATCH_FILE): $(XPATCH_DEPS) + $(MAKE) bounce TARGET=build-xpatch-using-host + + build-xpatch-using-host: + cd $(SCHEME_WORKAREA)/$(TARGET_MACH)/s && $(MAKE) -f Mf-cross m=$(MACH) xm=$(TARGET_MACH) Scheme="$(SCHEME_BIN)" SCHEMEHEAPDIRS="$(SCHEME_INC)" + + XPATCH = +-XPATCHcross = --xpatch $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++XPATCHcross = --xpatch $(XPATCH_FILE) + + racket.boot: racket.so + $(SCHEME) --script $(srcdir)/convert-to-boot.ss @BOOT_COMPRESS_COMP@ $(XPATCH@CROSS_MODE@) racket.so racket.boot $(TARGET_MACH) +@@ -410,7 +434,7 @@ install-cross: + $(MAKE) compile-xpatch.$(TARGET_MACH) + $(MAKE) library-xpatch.$(TARGET_MACH) + +-SCHEME_XPATCH = $(SCHEME_WORKAREA)/$(TARGET_MACH)/s/xpatch ++SCHEME_XPATCH = $(XPATCH_FILE) + + CROSS_SERVE_DEPS = $(srcdir)/mk-cross-serve.ss $(srcdir)/cross-serve.ss \ + $(srcdir)/../expander/env.ss $(srcdir)/../linklet/config.ss +diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure +index 21695a431a..1eeef57753 100755 +--- a/racket/src/cs/c/configure ++++ b/racket/src/cs/c/configure +@@ -654,6 +654,9 @@ MINGW + NOT_OSX + OSX + SETUP_BOOT_MODE ++USE_SCHEME_MODE ++MAKE_SCHEME_SCHEME ++MAKE_SCHEME_MODE + TT_CROSS_MODE + T_CROSS_MODE + CROSS_MODE +@@ -1448,7 +1451,7 @@ Optional Features: + --enable-docs build docs on install (enabled by default) + --enable-usersetup setup user-specific files on install + --enable-racket=<path> use <path> as Racket for build; or "auto" to create +- --enable-scheme=<path> use <path> as host's build directory for cross ++ --enable-scheme=<path> use <path> as host build for cross + --enable-mach=<mach> use Chez Scheme machine type <mach> + --enable-target=<mach> cross-build for Chez Scheme machine type <mach> + --enable-portable prefer portable to host-specific +@@ -2867,7 +2870,7 @@ show_explicitly_enabled "${enable_xonx}" "Unix style" + show_explicitly_enabled "${enable_libzo}" 'Compiled ".zo" files moved to lib' + + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + show_explicitly_enabled "${enable_portable}" "portable" +@@ -4745,9 +4748,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -6012,6 +6027,9 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags + + + ++ ++ ++ + + + +diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac +index 464ebe1760..aaee88156d 100644 +--- a/racket/src/cs/c/configure.ac ++++ b/racket/src/cs/c/configure.ac +@@ -23,7 +23,7 @@ AC_ARG_ENABLE(compressmore, [ --enable-compressmore compress compiled code ev + AC_ARG_ENABLE(compressboot, [ --enable-compressboot compress boot files]) + m4_include(../ac/path_arg.m4) + AC_ARG_ENABLE(racket, [ --enable-racket=<path> use <path> as Racket for build; or "auto" to create]) +-AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host's build directory for cross]) ++AC_ARG_ENABLE(scheme, [ --enable-scheme=<path> use <path> as host build for cross]) + AC_ARG_ENABLE(mach, [ --enable-mach=<mach> use Chez Scheme machine type <mach>]) + AC_ARG_ENABLE(target, [ --enable-target=<mach> cross-build for Chez Scheme machine type <mach>]) + m4_include(../ac/portable_arg.m4) +@@ -81,7 +81,7 @@ show_explicitly_disabled "${enable_compressboot}" "Compressed boot files" + show_explicitly_enabled "${enable_xonx}" "Unix style" + m4_include(../ac/path_show.m4) + show_explicitly_set "${enable_racket}" "Racket" +-show_explicitly_set "${enable_scheme}" "Chez Scheme build directory" ++show_explicitly_set "${enable_scheme}" "Chez Scheme for build" + show_explicitly_set "${enable_mach}" "machine type" + show_explicitly_set "${enable_target}" "cross-build machine type" + m4_include(../ac/portable_show.m4) +@@ -504,9 +504,21 @@ esac + + SCHEME_DIR=${srcdir}/../../ChezScheme + MAKE_BUILD_SCHEME=checkout ++USE_SCHEME_MODE="_built" ++MAKE_SCHEME_MODE="${T_CROSS_MODE}" + + if test "${enable_scheme}" != "" ; then +- CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ if test -d "${enable_scheme}" ; then ++ # Directory exists, so use it as a build directory ++ echo "Using supplied Scheme path as a build directory" ++ CS_HOST_WORKAREA_PREFIX="${enable_scheme}/" ++ else ++ # Directory does not exist, so assume it's an executable ++ echo "Using supplied Scheme path as an executable" ++ MAKE_SCHEME_MODE="${T_CROSS_MODE}-via-scheme" ++ MAKE_SCHEME_SCHEME="${enable_scheme}" ++ USE_SCHEME_MODE="_existing" ++ fi + fi + + if test "${enable_racket}" != "" ; then +@@ -821,6 +833,9 @@ AC_SUBST(DIFF_MACH) + AC_SUBST(CROSS_MODE) + AC_SUBST(T_CROSS_MODE) + AC_SUBST(TT_CROSS_MODE) ++AC_SUBST(MAKE_SCHEME_MODE) ++AC_SUBST(MAKE_SCHEME_SCHEME) ++AC_SUBST(USE_SCHEME_MODE) + AC_SUBST(SETUP_BOOT_MODE) + AC_SUBST(OSX) + AC_SUBST(NOT_OSX) +-- +2.32.0 + diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch new file mode 100644 index 0000000000..abf253486f --- /dev/null +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -0,0 +1,26 @@ +From aa792e707b1fbc5cc33691bfaee5828dc3fbebaa Mon Sep 17 00:00:00 2001 +From: Matthew Flatt <mflatt@racket-lang.org> +Date: Mon, 31 Jan 2022 15:31:22 -0700 +Subject: [PATCH] fix creation of tethered launchers + +Related to racket/racket#4133 + +(cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) +--- + share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt +index b1691472..9ef06c53 100644 +--- a/share/pkgs/gui-lib/mred/installer.rkt ++++ b/share/pkgs/gui-lib/mred/installer.rkt +@@ -72,4 +72,5 @@ + (list "-A" (path->string (find-system-path 'addon-dir))))) + + (define (config-flags) +- (list "-G" (path->string (find-config-dir)))) ++ (list "-X" (path->string (find-collects-dir)) ++ "-G" (path->string (find-config-dir)))) +-- +2.32.0 + diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index ec9e836a4c..00ec587eeb 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -43,6 +43,7 @@ (define-module (gnu packages racket) #:use-module (gnu packages libedit) #:use-module (gnu packages libffi) #:use-module (gnu packages multiprecision) + #:use-module (gnu packages ncurses) #:use-module (gnu packages sqlite) #:use-module (gnu packages tls) #:use-module (gnu packages xorg) @@ -95,6 +96,41 @@ (define-module (gnu packages racket) ;; ;; Code: +(define %racket-version "8.4") +;; ^ Remember to update racket-bootstrap-chez-bootfiles! +(define %racket-commit + (string-append "v" %racket-version)) +(define %racket-origin + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/racket") + (commit %racket-commit))) + (sha256 + (base32 "1vpl66gdgc8rnldmn8rmb7ar9l057jqjvgpfn29k57i3c5skr8s6")) + (file-name (git-file-name "racket" %racket-version)) + (patches (search-patches "racket-minimal-sh-via-rktio.patch" + ;; Remove by Racket 8.5: + "racket-enable-scheme-backport.patch")) + (modules '((guix build utils))) + (snippet + #~(begin + (use-modules (guix build utils)) + ;; Unbundle Chez submodules. + (with-directory-excursion "racket/src/ChezScheme" + ;; TODO: consider putting this in a (guix ...) or (guix build ...) + ;; module so it can be shared with the upstream Chez Scheme origin + ;; without cyclic issues. + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib"))) + ;; Unbundle libffi. + (delete-file-recursively "racket/src/bc/foreign/libffi"))))) + (define cfg-flag:sh-for-rktio `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" (assoc-ref %build-inputs "sh") @@ -128,41 +164,17 @@ (define src (define-public racket-minimal (package (name "racket-minimal") - (version "8.3") ; note: remember to also update racket! - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/racket/racket") - (commit (string-append "v" version)))) - (sha256 - "1i1jnv1wb0kanfg47hniafx2vhwjc33qqx66lq7wkf5hbmgsyws3") - (file-name (git-file-name name version)) - (patches (search-patches "racket-minimal-sh-via-rktio.patch")) - (modules '((guix build utils))) - (snippet - (with-imported-modules '((guix build utils)) - #~(begin - ;; Unbundle Chez submodules. - (with-directory-excursion "racket/src/ChezScheme" - ;; Remove bundled libraries (copied from 'chez-scheme'). - (for-each delete-file-recursively - '("stex" - "nanopass" - "lz4" - "zlib"))) - ;; Unbundle libffi. - (delete-file-recursively "racket/src/bc/foreign/libffi")))))) + (version %racket-version) + (source %racket-origin) (inputs `(;; common to all racket-minimal variants: ("openssl" ,openssl) ("sqlite" ,sqlite) - ("sh" ,bash-minimal) + ("sh" ,bash-minimal) ;; <- for `system` + ("ncurses" ,ncurses) ;; <- for #%terminal ;; only for CS ("zlib" ,zlib) - ("zlib:static" ,zlib "static") - ("lz4" ,lz4) - ("lz4:static" ,lz4 "static"))) + ("lz4" ,lz4))) (native-inputs `(("bootfiles" ,racket-bootstrap-chez-bootfiles) ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) @@ -263,9 +275,8 @@ (define-public racket-minimal-bc-3m (name "racket-minimal-bc-3m") (inputs (modify-inputs (package-inputs racket-minimal) - (delete "zlib" "zlib:static" "lz4" "lz4:static") - (prepend libffi ;; <- only for BC variants - ))) + (prepend libffi) ;; <- only for BC variants + (delete "zlib" "lz4"))) (native-inputs `(("libtool" ,libtool) ("racket" ,(if (%current-target-system) @@ -327,6 +338,11 @@ (define-public racket-bootstrap-chez-bootfiles (package (inherit racket-minimal) (name "racket-bootstrap-chez-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. (inputs `()) (native-inputs `(("racket" ,(if (%current-target-system) @@ -416,7 +432,7 @@ (define-public racket (package (inherit racket-minimal) (name "racket") - (version (package-version racket-minimal)) ; needed for origin uri to work + (version %racket-version) (source (origin (method url-fetch) @@ -425,7 +441,11 @@ (define-public racket %installer-mirrors)) (sha256 (base32 - "0jdr0y7scvv2a3sq456ifrgq0yfsbiwavdf2m86zmrapp481mby4")) + "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) (snippet #~(begin (use-modules (guix build utils) @@ -442,7 +462,14 @@ (define-public racket (with-directory-excursion "share/pkgs" (for-each delete-file-recursively '#+%main-repo-main-distribution-pkgs)) - #t)))) + ;; Minimal workaround for FSDG issue: + ;; see <https://github.com/racket/srfi/pull/15>. + ;; We will backport a better fix once we use Git + ;; origins for Racket packages. + (delete-file-recursively "share/pkgs/srfi-doc-nonfree") + (substitute* "share/pkgs/srfi/info.rkt" + (("\"srfi-doc-nonfree\"") + "")))))) (inputs `(("cairo" ,cairo) ("fontconfig" ,fontconfig) @@ -461,7 +488,7 @@ (define-public racket (native-inputs `(("racket" ,racket-minimal) ("extend-layer" ,extend-layer) - ("main-repo" ,(package-source racket-minimal)))) + ("main-repo" ,%racket-origin))) (arguments `(#:phases (modify-phases %standard-phases -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 03/24] gnu: racket: Use Git origins for Racket packages. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 02/24] gnu: racket: Update to 8.4 Philip McGrath @ 2022-02-27 21:28 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 04/24] gnu: racket-minimal: Use new package style Philip McGrath ` (21 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:28 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/patches/racket-gui-tethered-launcher-backport.patch: Adjust path. * gnu/packages/racket.scm (racket-packages-origin, simple-racket-origin): New procedures. (extend-layer): Rename to ... (configure-layer.rkt): ... this variable. Tweak command-line arguments. Adapt to 'config-tethered-apps-dir'. (racket): Stop inheriting from 'racket-minimal'. [version]: Use '%racket-version'. [source]: Stop using bundled tarball. [inputs]: Remove labels. Add 'racket-minimal' and package sources. [native-inputs]: Remove, since cross-compilation doesn't work yet. [arguments]: Rewrite to use G-expressions, package sources from 'inputs', an explicit 'install' phase, and the revised 'configure-layer.rkt'. --- ...acket-gui-tethered-launcher-backport.patch | 6 +- gnu/packages/racket.scm | 714 +++++++++++++----- 2 files changed, 539 insertions(+), 181 deletions(-) diff --git a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch index abf253486f..1e018eaa79 100644 --- a/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch +++ b/gnu/packages/patches/racket-gui-tethered-launcher-backport.patch @@ -7,13 +7,13 @@ Related to racket/racket#4133 (cherry picked from commit 563c68432f127729592f234ef30c31e92618b517) --- - share/pkgs/gui-lib/mred/installer.rkt | 3 ++- + gui-lib/mred/installer.rkt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui-lib/mred/installer.rkt b/gui-lib/mred/installer.rkt index b1691472..9ef06c53 100644 ---- a/share/pkgs/gui-lib/mred/installer.rkt -+++ b/share/pkgs/gui-lib/mred/installer.rkt +--- a/gui-lib/mred/installer.rkt ++++ b/gui-lib/mred/installer.rkt @@ -72,4 +72,5 @@ (list "-A" (path->string (find-system-path 'addon-dir))))) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 00ec587eeb..a37442edc2 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -28,7 +28,9 @@ (define-module (gnu packages racket) #:use-module (guix gexp) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (ice-9 match) + #:use-module (ice-9 exceptions) #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages bash) @@ -389,172 +391,504 @@ (define-public racket-bootstrap-chez-bootfiles Chez Scheme.") (license (list license:asl2.0))))) +(define (racket-packages-origin name origin specs) + "Extract from ORIGIN the sources for the Racket packages specified by SPECS, +a non-empty list of package specifications. In the resulting file-like +object, each package's source will be in the directory +\"/share/racket/pkgs/PKG/\", where PKG is the Racket name for the package. +The NAME will be used in the store file name for the resulting file-like +object. -(define %installer-mirrors - ;; Source: - ;; https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58 - ;; Matthew Flatt says: "note that many are commented out" - ;; INVARIANT: End with a trailing "/"! - '("https://mirror.racket-lang.org/installers/" - "https://www.cs.utah.edu/plt/installers/" - "https://plt.cs.northwestern.edu/racket-mirror/" - "https://mirror.csclub.uwaterloo.ca/racket/racket-installers/" - ;; Universität Tübingen is using a self-signed HTTPS certificate: - "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" - "https://racket.infogroep.be/" - )) +A package specification is a list of the form: -(define %main-repo-main-distribution-pkgs - ;; These are the packages developed in the main Racket Git repository - ;; that are part of the main distribution. - '("at-exp-lib" - "base" - "compiler-lib" - ;; NOT "compiler-test" - "compiler" - "net-doc" - "net-lib" - ;; NOT "net-test" - "net" - ;; NOT "plt-services" - ;; NOT "racket-benchmarks" - ;; NOT "racket-build-guide" - "racket-doc" - "racket-index" - "racket-lib" - ;; NOT "racket-test-core" - ;; NOT "racket-test-extra" - ;; NOT "racket-test" - "zo-lib")) + (PKG PATH) +where PATH is the path to the package source relative to ORIGIN---possibly +\".\". As a special case, a package specification may also be a string, which +is equivalent to: + + (PKG PKG) + +Examples: + +- \"expeditor\" +- (\"main-distribution\" \".\") +- (\"racket-lib\" \"pkgs/racket-lib\")" + (computed-file + (string-append "racket-pkg-" name "-sources") + (with-imported-modules `((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p (string-append #$output "/share/racket/pkgs")) + (chdir (string-append #$output "/share/racket/pkgs")) + #$@(map (match-lambda + ((? string? name) + #~(copy-recursively #$(file-append origin (string-append "/" name)) + #$name)) + ((name ".") + #~(copy-recursively #$origin #$name)) + ((name path) + #~(copy-recursively #$(file-append origin (string-append "/" path)) + #$name))) + specs))))) + +(define (simple-racket-origin repo hash specs) + "Like 'racket-packages-origin', but specialized for packages hosted at +\"https://github.com/racket/REPO\" with sha256 checksum HASH. REPO is also +used to build the name of the resulting store item." + (racket-packages-origin + repo + (origin + (method git-fetch) + (uri (git-reference + (url (format #f "https://github.com/racket/~a" repo)) + (commit %racket-commit))) + (sha256 hash) + (file-name (git-file-name (string-append "racket-" repo) + %racket-version))) + specs)) (define-public racket (package - (inherit racket-minimal) (name "racket") (version %racket-version) - (source - (origin - (method url-fetch) - (uri (map (lambda (base) - (string-append base version "/racket-src.tgz")) - %installer-mirrors)) - (sha256 - (base32 - "0dsv7br85nvh5gjfihznq9jb1dzas0f6gnv5qwc9zmb7yn75nrp5")) - (patches - ;; remove in Racket 8.5 - ;; see https://github.com/racket/racket/issues/4133 - (search-patches "racket-gui-tethered-launcher-backport.patch")) - (snippet - #~(begin - (use-modules (guix build utils) - (ice-9 match) - (ice-9 regex)) - ;; unbundle minimal Racket - (for-each delete-file-recursively - '("collects" - "doc" - "etc" - "README" - "src")) - ;; unbundle package sources included elsewhere - (with-directory-excursion "share/pkgs" - (for-each delete-file-recursively - '#+%main-repo-main-distribution-pkgs)) - ;; Minimal workaround for FSDG issue: - ;; see <https://github.com/racket/srfi/pull/15>. - ;; We will backport a better fix once we use Git - ;; origins for Racket packages. - (delete-file-recursively "share/pkgs/srfi-doc-nonfree") - (substitute* "share/pkgs/srfi/info.rkt" - (("\"srfi-doc-nonfree\"") - "")))))) + (source #f) (inputs - `(("cairo" ,cairo) - ("fontconfig" ,fontconfig) - ("glib" ,glib) - ("glu" ,glu) - ("gmp" ,gmp) - ("gtk+" ,gtk+) ; propagates gdk-pixbuf+svg - ("libjpeg" ,libjpeg-turbo) - ("libpng" ,libpng) - ("libx11" ,libx11) - ("mesa" ,mesa) - ("mpfr" ,mpfr) - ("pango" ,pango) - ("unixodbc" ,unixodbc) - ("libedit" ,libedit))) - (native-inputs - `(("racket" ,racket-minimal) - ("extend-layer" ,extend-layer) - ("main-repo" ,%racket-origin))) + (list + cairo + fontconfig + glib + glu + gmp + gtk+ ;; propagates gdk-pixbuf+svg + libjpeg-turbo + libpng + libx11 ;; ?? wayland ?? + mesa + mpfr + pango + unixodbc + libedit ;; TODO reconsider in light of expeditor and readline-gpl + racket-minimal ;; <-- TODO non-tethered layer + (simple-racket-origin + "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") + '("2d" "2d-doc" "2d-lib")) + (simple-racket-origin + "algol60" (base32 "09kj6asypmc24n29w0izc9p0q8hpga2hpkchsypfwn5c8zpvihlx") + '(("algol60" "."))) + (racket-packages-origin + "racket" %racket-origin + '(("base" "pkgs/base") ;; FIXME belongs in racket-minimal + ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal + ("at-exp-lib" "pkgs/at-exp-lib") + ("compiler" "pkgs/compiler") + ("compiler-lib" "pkgs/compiler-lib") + ("net" "pkgs/net") + ("net-doc" "pkgs/net-doc") + ("net-lib" "pkgs/net-lib") + ("racket-doc" "pkgs/racket-doc") + ("racket-index" "pkgs/racket-index") + ("sandbox-lib" "pkgs/sandbox-lib") + ("zo-lib" "pkgs/zo-lib"))) + (simple-racket-origin + "cext-lib" (base32 "00w38jpv88fpl4pgj6ndnysvn0s21rjvj0xhznay80msan0vc341") + '("cext-lib" "dynext-lib")) + (simple-racket-origin + "class-iop" (base32 "08z57q83cr7wnh6g8ah3hdhmsmf9zp1jfs7yvxv188l3hzvygy5l") + '("class-iop-lib")) + (simple-racket-origin + "compatibility" (base32 "0bfqwscjpyi325br5pa6g62g9c8lq18a80zp5g3d2qzn3n3mi6x0") + '("compatibility" "compatibility-doc" "compatibility-lib")) + (simple-racket-origin + "contract-profile" (base32 "1xm2z8g0dpv5d9h2sg680vx1a8ix9gbsdpxxb8qv1w7akp73paj3") + '(("contract-profile" "."))) + (simple-racket-origin + "data" (base32 "10iabgrk9alaggvksnyb0hdq7f1p30pq6pq2bcakvhzpxwiv1f55") + '("data" "data-doc" "data-enumerate-lib" "data-lib")) + (simple-racket-origin + "datalog" (base32 "0n5j5gnqh7g31mvgx19ggl18hirzbvq2r189lbngmnrmbc7b73fp") + '(("datalog" "."))) + (simple-racket-origin + "db" (base32 "1n02ja0yj3mjjhmz0yv04yfhyvrsznbljn8bjviyfxnm4xf9rcc5") + '("db" "db-doc" "db-lib")) + (simple-racket-origin + "deinprogramm" (base32 "1is6fapgv6rxfjz47nh6qf3kh7y7sjdinakaxqffi46gf1al8prd") + '("deinprogramm" "deinprogramm-signature")) + (simple-racket-origin + "distributed-places" (base32 "1dajpkj9balqcpv6cdk9hwjz592h1vq8rrx5vncariiac4vbdpa0") + '("distributed-places" "distributed-places-doc" "distributed-places-lib")) + (simple-racket-origin + "draw" (base32 "1xgjfbh70hqw67z88iqqajg98d04qwbzn6im2wj47rs28jxlm9ly") + '("draw" "draw-doc" "draw-lib")) + (simple-racket-origin + "drracket" (base32 "0m3l4an3nq2ycd1h287s1az2v2zprjbzd8if2x7d5r71vaj4i00c") + '("drracket" + "drracket-plugin-lib" + "drracket-tool" + "drracket-tool-doc" + "drracket-tool-lib" + "drracket-tool-text-lib")) + (simple-racket-origin + "ds-store" (base32 "0ajr27kipp4dr1qlisaghsb3h7lhhjwrfw2r79b5myczsa1mp661") + '("ds-store" "ds-store-doc" "ds-store-lib")) + (simple-racket-origin + "eli-tester" (base32 "0icx6wn14gjm8kdmq1jppqgq87sxkras4qb5xmdr6wigxafhjqyk") + '(("eli-tester" "."))) + (simple-racket-origin + "eopl" (base32 "1fmiixj6rxsgzwvgva8lvrvv0gl49v2405mp3s0i7ipis5c4n27s") + '(("eopl" "."))) + (simple-racket-origin + "errortrace" (base32 "14m7rhaxngj36070iw15am434hm438pfgmwjfsiqhsglz4pcxhip") + '("errortrace" "errortrace-doc" "errortrace-lib")) + (simple-racket-origin + "expeditor" (base32 "07djzxs6307l51mcsk3yr2g4g47ayxa3878g7sf5xhqdr4hd9vxf") + '("expeditor" "expeditor-doc" "expeditor-lib")) + (simple-racket-origin + "frtime" (base32 "0ydz2yn8vvv6z7brwlswcyx0f31a6y6d443i89rysfvd2xkhpfd5") + '(("frtime" "."))) + (simple-racket-origin + "future-visualizer" (base32 "1758qq769m0r14xf64sl2ix2l9z340kvapar0j7s5kdg42lmvnhm") + '("future-visualizer" + "future-visualizer-pict" + "future-visualizer-typed")) + (simple-racket-origin + "games" (base32 "0kpn3izlx1ccd0pj0dnvmnrhny51b85xy418a7psj70lz8j8415d") + '(("games" "."))) + (racket-packages-origin + "gui" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/gui") + (commit %racket-commit))) + (sha256 (base32 + "1x33jgrx3r32k7hgwr591z3xqv1m2r5nc4km2fnxv0ak2xa0j3gj")) + (patches + ;; remove in Racket 8.5 + ;; see https://github.com/racket/racket/issues/4133 + (search-patches "racket-gui-tethered-launcher-backport.patch")) + (file-name (git-file-name "racket-gui" %racket-version))) + '("gui" "gui-doc" "gui-lib" "tex-table")) + (simple-racket-origin + "gui-pkg-manager" (base32 "1ji9448d723nklqvycwdswj0ni28sabrncag14f9mx47did5myb5") + '("gui-pkg-manager-lib")) + (simple-racket-origin + "htdp" (base32 "0r4ykybcpr10y2db9rlza9pr0xh58nd7ac389mjcxp8g386hgihl") + '("htdp" "htdp-doc" "htdp-lib")) + (simple-racket-origin + "html" (base32 "18n1jnjgzfknc8nv8dppi85nb8q08gqdwkg6hfjk08x0p00anx2x") + '("html" "html-doc" "html-lib")) + (simple-racket-origin + "icons" (base32 "1s5a6j11fg3fdr6b7vm2q7q178d7q8b8igy73bs211r27qrd1gg7") + '(("icons" "."))) + (simple-racket-origin + "images" (base32 "0rpjxqw34bq5m08kh1ldl1mr7s9z1lyydxxcyzb292kqh9qiqvfl") + '("images" "images-doc" "images-gui-lib" "images-lib")) + (simple-racket-origin + "lazy" (base32 "176ylzgbdsbmqknpihaz519afq71pyjkv1h87j5v8jfbpbddyfsf") + '(("lazy" "."))) + (simple-racket-origin + "macro-debugger" (base32 "14hyrwbkffr61fk44l02xb47bhv5zccw0ymaa9kxld86hvyqhqbm") + '("macro-debugger" "macro-debugger-text-lib")) + (simple-racket-origin + "main-distribution" (base32 "0m2n9s32s8a4a2gn4ywrm9l8jycdm5ayi5w9kh5wchhrrw7qzq7y") + '(("main-distribution" "."))) + (simple-racket-origin + "make" (base32 "10852fj30bz5r46c3d99s37fkgy5yh44gb01j29sf3kxnhi0g2sa") + '(("make" "."))) + (simple-racket-origin + "math" (base32 "02sqbnvxvmvslk33b44fx4v93zafcvhva0cx8z21jqbl5wp217ac") + '("math" "math-doc" "math-lib")) + (simple-racket-origin + "mysterx" (base32 "11p9jzrafw0hizhl0cs4sxx7rv281185q8hryic2rpk0kzjdyr48") + '(("mysterx" "."))) + (simple-racket-origin + "mzcom" (base32 "0rc9pfj7gwm5azghqvcibz6si1x5s2v8mr2yngk7ssq9gzfbi6a4") + '(("mzcom" "."))) + (simple-racket-origin + "mzscheme" (base32 "192c52zi726h5wjamxrhivjw2waq1im0zpyxhbrkrxknm8x84bs9") + '("mzscheme" "mzscheme-doc" "mzscheme-lib")) + (racket-packages-origin + "net-cookies" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/RenaissanceBug/racket-cookies") + (commit %racket-commit))) + (sha256 (base32 + "0k0hifxhywl5c3hjcaiizc098dpyk001d981p572gly116yvjxc1")) + (file-name + (git-file-name "RenaissanceBug-racket-cookies" %racket-version))) + '("net-cookies" "net-cookies-doc" "net-cookies-lib")) + (racket-packages-origin + "optimization-coach" + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/stamourv/optimization-coach") + (commit %racket-commit))) + (sha256 (base32 + "0b27sw48d7rhz0hin88c7rbr9vpg1c23sn82nd4jkmq54h6gasr1")) + (file-name + (git-file-name "stamourv-optimization-coach" %racket-version))) + '(("optimization-coach" "."))) + (simple-racket-origin + "option-contract" (base32 "026b7n5l0c3024nymshz8zp1yhn493rdzgpflzfd52hj7awafqhk") + '("option-contract" "option-contract-doc" "option-contract-lib")) + (simple-racket-origin + "parser-tools" (base32 "08pvz4zramirzm3j64hbhjm0mmh5zfy37iv4s3vmq0rj49cr8fl3") + '("parser-tools" "parser-tools-doc" "parser-tools-lib")) + (simple-racket-origin + "pconvert" (base32 "00czi0p399mmyrvxyrs5kniizpkqfxyz2ncxqi2jy79a7wk79pb1") + '("pconvert-lib")) + (simple-racket-origin + "pict" (base32 "0g1iwdr6qh1xb0crhj96830vjjnbds409xbpqn7j5sh0ksy6vr5x") + '("pict" "pict-doc" "pict-lib")) + (simple-racket-origin + "pict-snip" (base32 "081nwiy4a0n4f7xws16hqbhf0j3kz5alizndi3nnyr3chm4kng6x") + '("pict-snip" "pict-snip-doc" "pict-snip-lib")) + (simple-racket-origin + "picturing-programs" (base32 "1g6xr39hx1j03gb3d4dljm3v91xcj2gfpq3dgy5xvplzr6cmmxgr") + '(("picturing-programs" "."))) + (simple-racket-origin + "plai" (base32 "0i983sh0r0zm2ng4j44m5aw9669kh5fhp91bzpc9jm280rfcqvyl") + '("plai" "plai-doc" "plai-lib")) + (simple-racket-origin + "planet" (base32 "0r2yqrzrmdjjyr14k6hhlzc5kzrcx3583m1s02mhrcmpfw0s85w9") + '("planet" "planet-doc" "planet-lib")) + (simple-racket-origin + "plot" (base32 "07kq32si34ybcwz8idxxcrzssg8diyrp1nfgkcj0mmvr45321zm7") + '("plot" "plot-compat" "plot-doc" "plot-gui-lib" "plot-lib")) + (simple-racket-origin + "preprocessor" (base32 "1p5aid58ifnjy4xl0ysh85cq39k25661v975jrpk182z3k5621mg") + '(("preprocessor" "."))) + (simple-racket-origin + "profile" (base32 "179i86lyby29nywz60l4vnadi02w8b12h7501nm5h5g4pq9jjmbb") + '("profile" "profile-doc" "profile-lib")) + (racket-packages-origin + "quickscript" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/Metaxal/quickscript") + (commit %racket-commit))) + (sha256 (base32 + "100g3yqhbjdq06b6l6d72ywsw29awgy8crqg33wj7h12xq07nzcr")) + (file-name (git-file-name "Metaxal-quickscript" %racket-version))) + '(("quickscript" "."))) + (simple-racket-origin + "r5rs" (base32 "1g3cysj7z88r38vkzvi8g2fb2hn4yg1fdhy5smxw303jxgl3inp6") + '("r5rs" "r5rs-doc" "r5rs-lib")) + (simple-racket-origin + "r6rs" (base32 "0b1ymzdp10r0flw2acbidjsh5ma1pm5hy54jss37sxf89z3xbvm4") + '("r6rs" "r6rs-doc" "r6rs-lib")) + (racket-packages-origin + "racket-cheat" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/jeapostrophe/racket-cheat") + (commit %racket-commit))) + (sha256 (base32 + "06wcj558rzkbl2bwkmikyspya9v1f4iwlzwnwxpkc33h2xapwabr")) + (file-name + (git-file-name "jeapostrophe-racket-cheat" %racket-version))) + '(("racket-cheat" "."))) + (simple-racket-origin + "racklog" (base32 "1rgrvwy3kr9b9w5cghsffiv3ly00yfvvzr5xaaw83g1w7yin0mnb") + '(("racklog" "."))) + (simple-racket-origin + "rackunit" (base32 "057z31rja6h3nabh5b2xgwfrzmlm6h1cv1qcgf3xfy4g2q5dqn5p") + '("rackunit" + "rackunit-doc" + "rackunit-gui" + "rackunit-lib" + "rackunit-plugin-lib" + "rackunit-typed" + "schemeunit" + "testing-util-lib")) + (simple-racket-origin + "readline" (base32 "13kbcn2wchv82d709mw3r8n37bk8iwq0y4kpvm9dbzx0w2pxkfwn") + '("readline" "readline-doc" "readline-lib")) + (simple-racket-origin + "realm" (base32 "0hxcgla08iack54j8v40fj51811chpy66ym2zq76zb52c7kzn0hi") + '(("realm" "."))) + (simple-racket-origin + "redex" (base32 "0vlgxbnbgrlihk1hh5zd6hsc4566ldi4q76f87z5vai54dxkwy2f") + '("redex" + "redex-benchmark" + "redex-doc" + "redex-examples" + "redex-gui-lib" + "redex-lib" + "redex-pict-lib")) + (simple-racket-origin + "sasl" (base32 "0ibh4wb4gn8pggx6gkv4vk4d6rwzn5nrvjibhvkzhaynf6lhb824") + '("sasl" "sasl-doc" "sasl-lib")) + (simple-racket-origin + "scheme-lib" (base32 "0pcf0y8rp4qyjhaz5ww5sr5diq0wpcdfrrnask7zapyklzx1jx8x") + '(("scheme-lib" "."))) + (simple-racket-origin + "scribble" (base32 "0rgvnsykrxkah6s5fw1vyp9lxsb4z9w6hgwk5j6wbwjp2gsfczbm") + '("scribble" + "scribble-doc" + "scribble-html-lib" + "scribble-lib" + "scribble-text-lib")) + (simple-racket-origin + "serialize-cstruct-lib" + (base32 "1rq3n1fa7ldjwx3lrh9ybhig7jlsw1crpzyklbzp3xqdw6jymfnz") + '(("serialize-cstruct-lib" "."))) + (simple-racket-origin + "sgl" (base32 "0nkymhdyjrwi5h199j4w5zh7y3x3ai42gsiwxzh0hy7yqrqqg9zv") + '(("sgl" "."))) + (simple-racket-origin + "shell-completion" (base32 "04m144gy2mp4fiq6rcbf12wjr8mws8k9scfhg9lc38vqppp4lxsj") + '(("shell-completion" "."))) + (simple-racket-origin + "simple-tree-text-markup" + (base32 "0fyd9gfz6bnv0m1901wv5mnhc05rm8hw9i6ddrqx33hs6qsg2zqr") + '("simple-tree-text-markup" + "simple-tree-text-markup-doc" + "simple-tree-text-markup-lib")) + (simple-racket-origin + "slatex" (base32 "0pkm2isbbdk63slrbsxcql7rr0wdrw5kapw1xq4ps5k8dhlzv8x0") + '(("slatex" "."))) + (simple-racket-origin + "slideshow" (base32 "1znv1i2d0610hhy71q932xy7wka00q3q50in1xfnk8ibg7nzkagm") + '("slideshow" "slideshow-doc" "slideshow-exe" "slideshow-lib" "slideshow-plugin")) + (simple-racket-origin + "snip" (base32 "01r9wc5xr3q3n4yyif6j0a37rgdzmpslxn05k13ksik73b3wj6hj") + '("snip" "snip-lib")) + (simple-racket-origin + "typed-racket" (base32 "1462kj9yswsxbnw71casylzlvhd7cxrml2v9j7rcsnn9hmrqx4vv") + '("source-syntax" + "typed-racket" + "typed-racket-compatibility" + "typed-racket-doc" + "typed-racket-lib" + "typed-racket-more")) + (racket-packages-origin + "srfi" (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/racket/srfi") + ;; Includes an FSDG fix: return to %racket-commit in 8.5. + ;; See <https://github.com/racket/srfi/pull/15>. + (commit "7243029b135741ce08ae30f877e2f49a2a460b22"))) + (sha256 (base32 + "0aqbcdv2dfc2xnk0h6zfi56p7bpwqji8s88qds3d03hhh9k28gvn")) + ;; Use the relevant version for srfi-doc and srfi-lib, + ;; since we're using a newer commit than the v8.4 tag. + (file-name (git-file-name "racket-srfi" "1.1"))) + '("srfi" "srfi-doc" "srfi-lib" "srfi-lite-lib")) + (simple-racket-origin + "string-constants" (base32 "1qizjq4n0hzdgdcjjpr94464gsywpsk2g9mnvwzqr7dcqbrsfvn6") + '("string-constants" "string-constants-doc" "string-constants-lib")) + (simple-racket-origin + "swindle" (base32 "164gdsphjzdl2vv7zxz7dfk9jwax8njpmim6sidm8qz8a8589y67") + '(("swindle" "."))) + (simple-racket-origin + "syntax-color" (base32 "1vf2fc3qvx8a1igi7swsg8gaqhx786sa0vqxd18xhbsidfgb5ywp") + '("syntax-color" "syntax-color-doc" "syntax-color-lib")) + (simple-racket-origin + "trace" (base32 "070ihla5j796hdarn5wxdwn4xj0xnkm50shgh49jy994mribvhia") + '(("trace" "."))) + (simple-racket-origin + "unix-socket" (base32 "02dfwas5ynbpyz74w9kwb4wgb37y5wys7svrlmir8k0n9ph9vq0y") + '("unix-socket" "unix-socket-doc" "unix-socket-lib")) + (simple-racket-origin + "web-server" (base32 "1zgb6jl7zx6258ljs8f3lvryrq5n5zpd71dqzr698m92kw3x2pkn") + '("web-server" "web-server-doc" "web-server-lib")) + (simple-racket-origin + "wxme" (base32 "1qp5gr9gqsakiq3alw6m4yyv5vw4i3hp4y4nhq8vl2nkjmirvn0b") + '("wxme" "wxme-lib")) + (simple-racket-origin + "xrepl" (base32 "12zjgsy5zqm3fck3ihg4a70wj56s2cnnjyb4jlfi5nnsfqyrnxg3") + '("xrepl" "xrepl-doc" "xrepl-lib")))) + (build-system gnu-build-system) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'configure 'unpack-packages - (let ((unpack (assoc-ref %standard-phases 'unpack))) - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out")) - (pkgs-dir (string-append prefix "/share/racket/pkgs"))) - (mkdir-p pkgs-dir) - (copy-recursively - "share/links.rktd" - (string-append prefix "/share/racket/links.rktd")) - (copy-recursively "share/pkgs" pkgs-dir) - ;; NOTE: unpack changes the working directory - (unpack #:source (assoc-ref (or native-inputs inputs) - "main-repo")) - (for-each (lambda (pkg) - (define dest (string-append pkgs-dir "/" pkg)) - (mkdir-p dest) - (copy-recursively (string-append "pkgs/" pkg) - dest)) - ',%main-repo-main-distribution-pkgs) - #t)))) - (replace 'configure - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let ((racket (assoc-ref (or native-inputs inputs) "racket")) - (prefix (assoc-ref outputs "out"))) - (apply invoke - (string-append racket "/bin/racket") - (assoc-ref inputs "extend-layer") - racket - prefix - (map - (lambda (lib) - (string-append (assoc-ref inputs lib) "/lib")) - '("cairo" - "fontconfig" - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))) - #t))) - (replace 'build - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (invoke (string-append (assoc-ref (or native-inputs inputs) - "racket") - "/bin/racket") - "--config" - (string-append (assoc-ref outputs "out") - "/etc/racket") - "-l" - "raco" - "setup") - #t)) - (delete 'install)) - ;; we still don't have these: - #:tests? #f)) + ;; We're using #:configure-flags to pass flags for + ;; `configure-layer.rkt` and #:make-flags to pass arguments for + ;; `raco pkg install`. + (list + #:configure-flags + #~`("--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit"))))) + #:make-flags #~`("main-distribution") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((racket (search-input-file inputs "bin/racket"))) + (apply invoke + racket + #$configure-layer.rkt + `(,@configure-flags + ,(dirname (dirname racket)) + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket (search-input-file inputs "/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -564,17 +898,20 @@ (define dest (string-append pkgs-dir "/" pkg)) The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) - +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) -(define extend-layer +(define configure-layer.rkt (scheme-file - "extend-layer.rkt" + "configure-layer.rkt" `(module - extend-layer racket/base + configure-layer racket/base (require racket/cmdline racket/match racket/file + racket/port racket/list racket/pretty) (define config-file-pth @@ -584,8 +921,14 @@ (define (build-path-string . args) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define extra-foreign-lib-search-dirs '()) (command-line - #:args (parent-layer prefix . lib-dir*) + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) (let* ([config (for/fold ([config (file->value (build-path parent-layer @@ -615,27 +958,42 @@ (define rx:racket (build-path-string parent-layer pth)) (filter values (hash-ref config search-key null)))))] [config - (hash-set config - 'apps-dir - (build-path-string prefix "share/applications"))] + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] [config - ;; place new foreign lib-search-dirs before old - ;; foreign dirs, but after Racket layers - (let-values - ([(rkt extra) - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - (hash-ref config 'lib-search-dirs))]) - (hash-set config - 'lib-search-dirs - (append rkt - lib-dir* - extra)))] + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaround Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] [bin-dir (hash-ref config 'bin-dir)] [config (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) 'config-tethered-console-bin-dir bin-dir 'config-tethered-gui-bin-dir bin-dir)] [new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 04/24] gnu: racket-minimal: Use new package style. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (2 preceding siblings ...) 2022-02-27 21:28 ` [bug#53878] [PATCH v7 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath ` (20 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (cfg-flag:sh-for-rktio, cfg-flag:enable-lt, cfg-glag:enable-racket): Change to G-expressions and combine in ... (racket-vm-common-configure-flags): ... this new thunk. (unpack-nanopass+stex): Change to G-expression and move to ... (make-unpack-nanopass+stex): ... this new thunk. (racket-bootstrap-chez-bootfiles): Rename to ... (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable, and stop inheriting from 'racket-minimal'. [native-inputs]: Remove labels. [build-system]: Use 'copy-build-system'. [arguments]: Use G-expressions. Install under "lib". (racket-minimal)[inputs, native-inputs]: Remove labels. [arguments]: Use G-expressions. Avoid 'assoc-ref'. Adapt to changes in 'chez-scheme-for-racket-bootstrap-bootfiles'. (racket-minimal-bc-3m)[native-inputs]: Remove labels. [arguments]: Use G-expressions. (racket-minimal-bc-cgc)[native-inputs]: Remove labels. [arguments]: Use G-expressions. --- gnu/packages/racket.scm | 332 ++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 169 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a37442edc2..eb87eaa492 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -26,6 +26,7 @@ (define-module (gnu packages racket) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) @@ -99,7 +100,7 @@ (define-module (gnu packages racket) ;; Code: (define %racket-version "8.4") -;; ^ Remember to update racket-bootstrap-chez-bootfiles! +;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin @@ -133,34 +134,42 @@ (define %racket-origin ;; Unbundle libffi. (delete-file-recursively "racket/src/bc/foreign/libffi"))))) -(define cfg-flag:sh-for-rktio - `(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - (assoc-ref %build-inputs "sh") - "/bin/sh")) -(define cfg-flag:enable-lt - `(string-append "--enable-lt=" - (assoc-ref %build-inputs "libtool") - "/bin/libtool")) -(define cfg-flag:enable-racket - `(let ((racket (assoc-ref %build-inputs "racket"))) - (string-append "--enable-racket=" - racket - "/bin/racket"))) +(define (racket-vm-common-configure-flags) + ;; under a lambda abstraction to avoid evaluating bash-minimal too early. + #~`(,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/libtool")) + => (lambda (libtool) + (list (string-append "--enable-lt=" libtool)))) + (else + '())) + ,@(cond + ((false-if-exception + (search-input-file %build-inputs "/bin/racket")) + => (lambda (racket) + (list (string-append "--enable-racket=" racket)))) + (else + '())) + ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" + #$(file-append bash-minimal "/bin/sh")))) -(define unpack-nanopass+stex - ;; Copied from chez-scheme. - ;; TODO: Eventually, we should refactor Chez Scheme - ;; enough to share more directly, so that we can make - ;; Racket's version of Chez avalable as a Guix package, - ;; e.g. for architectures not supported upstream. - ;; For now, we let Racket drive the Chez build process - ;; other than this step. - `(for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex"))) +(define (make-unpack-nanopass+stex) + ;; Adapted from chez-scheme. + ;; Thunked to avoid evaluating 'chez-scheme' too early. + ;; TODO: Refactor enough to share this directly. + #~(begin + (copy-recursively + #$(match (assoc-ref (package-native-inputs chez-scheme) + "nanopass") + ((src) + src)) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) (define-public racket-minimal @@ -169,91 +178,87 @@ (define-public racket-minimal (version %racket-version) (source %racket-origin) (inputs - `(;; common to all racket-minimal variants: - ("openssl" ,openssl) - ("sqlite" ,sqlite) - ("sh" ,bash-minimal) ;; <- for `system` - ("ncurses" ,ncurses) ;; <- for #%terminal - ;; only for CS - ("zlib" ,zlib) - ("lz4" ,lz4))) + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for CS + zlib + lz4)) (native-inputs - `(("bootfiles" ,racket-bootstrap-chez-bootfiles) - ,@(package-native-inputs racket-bootstrap-chez-bootfiles))) + (list chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m)) (build-system gnu-build-system) (arguments - `(#:configure-flags - (list "--enable-csonly" - "--enable-libz" - "--enable-liblz4" - ,cfg-flag:enable-racket - ,cfg-flag:sh-for-rktio) - #:out-of-source? #true - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main distribution. - #:tests? #f - #:modules ((ice-9 match) + (list + #:configure-flags + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) (guix build gnu-build-system) (guix build utils)) - #:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (string-append (assoc-ref inputs "bootfiles") "/boot") - "boot")) - #t)) - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f ,@(map (lambda (lib) - (string-append (assoc-ref inputs lib) - "/lib")) - '("openssl" - "sqlite")))) - (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - ,version - "/catalog/") - #f)))))) - #t)) - (add-before 'configure 'change-directory - (lambda _ - (chdir "racket/src") - #t)) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda* (#:key outputs #:allow-other-keys) - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append (assoc-ref outputs "out") - "/share/racket/pkgs")) - #t))))) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))) + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs + . (,(string-append + "https://download.racket-lang.org/releases/" + #$(package-version this-package) + "/catalog/") + #f)))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) (home-page "https://racket-lang.org") (synopsis "Racket without bundled packages such as DrRacket") (description @@ -269,7 +274,6 @@ (define (write-racket-hash alist) ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) - (define-public racket-minimal-bc-3m (hidden-package (package @@ -280,21 +284,19 @@ (define-public racket-minimal-bc-3m (prepend libffi) ;; <- only for BC variants (delete "zlib" "lz4"))) (native-inputs - `(("libtool" ,libtool) - ("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc)))) + (list libtool + (if (%current-target-system) + racket-minimal + racket-minimal-bc-cgc))) (arguments (substitute-keyword-arguments (package-arguments racket-minimal) ((#:configure-flags _ '()) - `(list "--enable-bconly" - ,cfg-flag:enable-racket - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)) - ((#:phases usual-phases) - `(modify-phases ,usual-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))) + ((#:phases cs-phases) + #~(modify-phases #$cs-phases + (delete 'unpack-nanopass+stex) + (delete 'unpack-bootfiles))))) (synopsis "Minimal Racket with the BC [3M] runtime system") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written @@ -309,19 +311,16 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) - (define-public racket-minimal-bc-cgc (package (inherit racket-minimal-bc-3m) (name "racket-minimal-bc-cgc") - (native-inputs - (alist-delete "racket" (package-native-inputs racket-minimal-bc-3m))) + (native-inputs (list libtool)) (arguments (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) ((#:configure-flags _ '()) - `(list "--enable-cgcdefault" - ,cfg-flag:enable-lt - ,cfg-flag:sh-for-rktio)))) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags))))) (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or ``bytecode'') implementation is not recommended for general use. It uses @@ -334,47 +333,42 @@ (define-public racket-minimal-bc-cgc also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector."))) - -(define-public racket-bootstrap-chez-bootfiles - (hidden-package - (package - (inherit racket-minimal) - (name "racket-bootstrap-chez-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (inputs `()) - (native-inputs - `(("racket" ,(if (%current-target-system) - racket-minimal - racket-minimal-bc-3m)) - ("stex" ,@(assoc-ref (package-native-inputs chez-scheme) "stex")) - ("nanopass" ,@(assoc-ref (package-native-inputs chez-scheme) - "nanopass")))) - (arguments - `(#:phases - (modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key inputs native-inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - ,unpack-nanopass+stex) - #t)) - (delete 'configure) - (delete 'patch-generated-file-shebangs) - (replace 'build - (lambda* (#:key inputs outputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (invoke (string-append (assoc-ref inputs "racket") - "/bin/racket") - "rktboot/main.rkt" - "--dest" (assoc-ref outputs "out"))) - #t)) - (delete 'check) - (delete 'install)))) - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source %racket-origin) + (inputs `()) + (native-inputs (list racket-minimal-bc-3m)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$(make-unpack-nanopass+stex))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/bin/racket") + "rktboot/main.rkt")))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it requires ``bootfiles'' containing the Scheme-implemented portions compiled for the current platform. (Chez can then cross-compile bootfiles for all other supported platforms.) @@ -389,7 +383,7 @@ (define-public racket-bootstrap-chez-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream Chez Scheme.") - (license (list license:asl2.0))))) + (license (list license:asl2.0)))) (define (racket-packages-origin name origin specs) "Extract from ORIGIN the sources for the Racket packages specified by SPECS, -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 05/24] gnu: racket-minimal: Don't configure non-existant catalogs. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (3 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 04/24] gnu: racket-minimal: Use new package style Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath ` (19 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal)[arguments]<#:phases>: Change 'initialize-config.rktd' to only add a release catalog when the package version is a release version. --- gnu/packages/racket.scm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index eb87eaa492..dc392fb27d 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -231,6 +231,15 @@ (define (write-racket-hash alist) (format #t "(~s . ~s)" k v))) alist) (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) (mkdir-p "racket/etc") (with-output-to-file "racket/etc/config.rktd" (lambda () @@ -239,12 +248,8 @@ (define (write-racket-hash alist) . (#f #$(file-append (this-package-input "openssl") "/lib") #$(file-append (this-package-input "sqlite") "/lib"))) (build-stamp . "") - (catalogs - . (,(string-append - "https://download.racket-lang.org/releases/" - #$(package-version this-package) - "/catalog/") - #f)))))))) + (catalogs ,@maybe-release-catalog + #f))))))) (add-before 'configure 'chdir (lambda _ (chdir "racket/src"))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (4 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath ` (18 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Having the package inheritance chain go in the same direction as the bootstrapping chain, rather than the opposite, is less confusing. In some cases, it can also help to avoid unnecessary rebuilds. * gnu/packages/racket.scm (racket-minimal-bc-cgc): Change to be the root of the package inheritance chain. [version, source, inputs, native-inputs, build-system, arguments, home-page, license]: Inline formerly inherited values. (racket-minimal-bc-3m): Inherit from 'racket-minimal-bc-cgc' rather than 'racket-minimal'. [inputs, native-inputs, arguments, license]: Adjust accordingly. (racket-minimal): Inherit from 'racket-minimal-bc-3m'. [inputs, native-inputs, arguments, license]: Adjust accordingly. [properties]: Override effect of 'hidden-package'. --- gnu/packages/racket.scm | 130 +++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 63 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index dc392fb27d..8d12a96f22 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr> ;;; Copyright © 2020 Pierre Neidhardt <mail@ambrevar.xyz> -;;; Copyright © 2021 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2021 jgart <jgart@dismail.de> ;;; ;;; This file is part of GNU Guix. @@ -172,9 +172,9 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal +(define-public racket-minimal-bc-cgc (package - (name "racket-minimal") + (name "racket-minimal-bc-cgc") (version %racket-version) (source %racket-origin) (inputs @@ -184,19 +184,14 @@ (define-public racket-minimal sqlite bash-minimal ;; <- for `system` ncurses ;; <- for #%terminal - ;; only for CS - zlib - lz4)) - (native-inputs - (list chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m)) + ;; only for BC variants: + libffi)) + (native-inputs (list libtool)) ;; <- only for BC variants (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-csonly" - "--enable-libz" - "--enable-lz4" + #~(cons* "--enable-cgcdefault" #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main @@ -210,17 +205,6 @@ (define-public racket-minimal (guix build utils)) #:phases #~(modify-phases %standard-phases - (add-after 'unpack 'unpack-nanopass+stex - (lambda args - (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))) (add-before 'configure 'initialize-config.rktd (lambda* (#:key inputs #:allow-other-keys) (define (write-racket-hash alist) @@ -265,43 +249,37 @@ (define maybe-release-catalog ;; rmdir because we want an error if it isn't empty (rmdir (string-append #$output "/share/racket/pkgs"))))))) (home-page "https://racket-lang.org") - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or +``bytecode'') implementation is not recommended for general use. It uses +CGC (a ``Conservative Garbage Collector''), which was succeeded as default in +PLT Scheme version 370 (which translates to 3.7 in the current versioning +scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the +Racket CS implementation. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") +Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +also be used for embedding applications without the annotations needed in C +code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) + (license (list license:lgpl3+ license:asl2.0 license:expat)) + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (properties `((hidden? . #t))))) (define-public racket-minimal-bc-3m (hidden-package (package - (inherit racket-minimal) + (inherit racket-minimal-bc-cgc) (name "racket-minimal-bc-3m") - (inputs - (modify-inputs (package-inputs racket-minimal) - (prepend libffi) ;; <- only for BC variants - (delete "zlib" "lz4"))) (native-inputs - (list libtool - (if (%current-target-system) - racket-minimal - racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (prepend racket-minimal-bc-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal) + (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" - #$(racket-vm-common-configure-flags))) - ((#:phases cs-phases) - #~(modify-phases #$cs-phases - (delete 'unpack-nanopass+stex) - (delete 'unpack-bootfiles))))) + #$(racket-vm-common-configure-flags))))) (synopsis "Minimal Racket with the BC [3M] runtime system") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written @@ -316,27 +294,53 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-cgc +(define-public racket-minimal (package (inherit racket-minimal-bc-3m) - (name "racket-minimal-bc-cgc") - (native-inputs (list libtool)) + (name "racket-minimal") + (inputs + (modify-inputs (package-inputs racket-minimal-bc-cgc) + (prepend zlib lz4) + (delete "libffi"))) + (native-inputs + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (delete "libtool") + (prepend chez-scheme-for-racket-bootstrap-bootfiles + racket-minimal-bc-3m))) (arguments (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) + ((#:phases bc-phases) + #~(modify-phases #$bc-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (with-directory-excursion "racket/src/ChezScheme" + #$(make-unpack-nanopass+stex)))) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "racket/src/ChezScheme" + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot")))))) ((#:configure-flags _ '()) - #~(cons "--enable-cgcdefault" - #$(racket-vm-common-configure-flags))))) - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or -``bytecode'') implementation is not recommended for general use. It uses -CGC (a ``Conservative Garbage Collector''), which was succeeded as default in -PLT Scheme version 370 (which translates to 3.7 in the current versioning -scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the -Racket CS implementation. + #~(cons* "--enable-csonly" + "--enable-libz" + "--enable-lz4" + #$(racket-vm-common-configure-flags))))) + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may -also be used for embedding applications without the annotations needed in C -code to use the 3M garbage collector."))) +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + (properties `()) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) (define-public chez-scheme-for-racket-bootstrap-bootfiles (package -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 07/24] gnu: racket-minimal: Adjust indentation. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (5 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath ` (17 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal-bc-cgc): Use 'hidden-package' rather than 'properties'. (racket-minimal-bc-3m): Remove redundant 'hidden-package' wrapper. --- gnu/packages/racket.scm | 201 ++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 101 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 8d12a96f22..3667f2df9d 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -173,84 +173,87 @@ (define (make-unpack-nanopass+stex) (define-public racket-minimal-bc-cgc - (package - (name "racket-minimal-bc-cgc") - (version %racket-version) - (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) - (native-inputs (list libtool)) ;; <- only for BC variants - (build-system gnu-build-system) - (arguments - (list - #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) - ;; Tests are in packages like racket-test-core and - ;; main-distribution-test that aren't part of the main - ;; distribution. - #:tests? #f - ;; Upstream recommends #:out-of-source?, and it does - ;; help with debugging, but it confuses `install-license-files`. - #:modules '((ice-9 match) - (ice-9 regex) - (guix build gnu-build-system) - (guix build utils)) - #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) - (home-page "https://racket-lang.org") - (synopsis "Old Racket implementation used for bootstrapping") - (description "This variant of the Racket BC (``before Chez'' or + ;; Eventually, it may make sense for some vm packages to not be hidden, + ;; but this one is especially likely to remain hidden. + (hidden-package + (package + (name "racket-minimal-bc-cgc") + (version %racket-version) + (source %racket-origin) + (inputs + (list + ;; common to all racket-minimal variants: + openssl + sqlite + bash-minimal ;; <- for `system` + ncurses ;; <- for #%terminal + ;; only for BC variants: + libffi)) + (native-inputs (list libtool)) ;; <- only for BC variants + (build-system gnu-build-system) + (arguments + (list + #:configure-flags + #~(cons* "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) + ;; Tests are in packages like racket-test-core and + ;; main-distribution-test that aren't part of the main + ;; distribution. + #:tests? #f + ;; Upstream recommends #:out-of-source?, and it does + ;; help with debugging, but it confuses `install-license-files`. + #:modules '((ice-9 match) + (ice-9 regex) + (guix build gnu-build-system) + (guix build utils)) + #:phases + #~(modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((lib-search-dirs + . (#f #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib"))) + (build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (add-after 'install 'remove-pkgs-directory + ;; If the configured pkgs-dir exists, "pkgs.rktd" does not + ;; exist, and a lock file does not exist, commands like + ;; `raco pkg show` will try to create a lock file and fail + ;; due to the read-only store. + ;; Arguably this may be a bug in `pkg/private/lock`: + ;; see <https://github.com/racket/racket/issues/3851>. + ;; As a workaround, remove the directory. + (lambda args + ;; rmdir because we want an error if it isn't empty + (rmdir (string-append #$output "/share/racket/pkgs"))))))) + (home-page "https://racket-lang.org") + (synopsis "Old Racket implementation used for bootstrapping") + (description "This variant of the Racket BC (``before Chez'' or ``bytecode'') implementation is not recommended for general use. It uses CGC (a ``Conservative Garbage Collector''), which was succeeded as default in PLT Scheme version 370 (which translates to 3.7 in the current versioning @@ -260,28 +263,24 @@ (define maybe-release-catalog Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:lgpl3+ license:asl2.0 license:expat)) - ;; Eventually, it may make sense for some vm packages to not be hidden, - ;; but this one is especially likely to remain hidden. - (properties `((hidden? . #t))))) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat))))) (define-public racket-minimal-bc-3m - (hidden-package - (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") - (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) - (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) - ((#:configure-flags _ '()) - #~(cons "--enable-bconly" - #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") - (description "The Racket BC (``before Chez'' or ``bytecode'') + (package + (inherit racket-minimal-bc-cgc) + (name "racket-minimal-bc-3m") + (native-inputs + (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (prepend racket-minimal-bc-cgc))) + (arguments + (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + ((#:configure-flags _ '()) + #~(cons "--enable-bconly" + #$(racket-vm-common-configure-flags))))) + (synopsis "Minimal Racket with the BC [3M] runtime system") + (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different @@ -290,9 +289,9 @@ (define-public racket-minimal-bc-3m This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'').") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:lgpl3+ license:asl2.0 license:expat))))) + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:lgpl3+ license:asl2.0 license:expat)))) (define-public racket-minimal (package -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 08/24] gnu: racket-minimal: Add "debug" output. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (6 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath ` (16 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-minimal-bc-cgc)[outputs]: Add "debug". (racket-vm-common-configure-flags): Add "--disable-strip". --- gnu/packages/racket.scm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 3667f2df9d..011577cc2e 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -151,7 +151,8 @@ (define (racket-vm-common-configure-flags) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" - #$(file-append bash-minimal "/bin/sh")))) + #$(file-append bash-minimal "/bin/sh")) + "--disable-strip")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -190,6 +191,7 @@ (define-public racket-minimal-bc-cgc ;; only for BC variants: libffi)) (native-inputs (list libtool)) ;; <- only for BC variants + (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 09/24] gnu: configure-layer.rkt: Adjust indentation. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (7 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath ` (15 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (configure-layer.rkt): Wrap 'command-line' in 'define-values' to reduce rightward drift. --- gnu/packages/racket.scm | 164 ++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 011577cc2e..3877837d38 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -926,84 +926,86 @@ (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) (define extra-foreign-lib-search-dirs '()) - (command-line - #:once-each - [("--extra-foreign-lib-search-dirs") dir-list - "foreign library directories, as a list of strings in `read` syntax" - (set! extra-foreign-lib-search-dirs - (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (let* ([config - (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) - (hash-set* - config - main-key - (build-path-string prefix pth) - search-key - (list* #f - (hash-ref config - main-key - (build-path-string parent-layer pth)) - (filter values (hash-ref config search-key null)))))] - [config - (hash-update config - 'lib-search-dirs - (lambda (dirs) - ;; add after other layers, but before older - ;; foreign lib search directories - (define-values [rkt old-foreign-dirs] - (partition (lambda (pth) - (or (not pth) - (regexp-match? rx:racket pth))) - dirs)) - (append rkt - extra-foreign-lib-search-dirs - old-foreign-dirs)))] - [config - (hash-set* config - 'apps-dir - (build-path-string prefix "share/applications") - 'absolute-installation? #t - ;; Let Guix coexist with other installation - ;; methods without clobbering user-specific packages. - ;; This could be set in various places, but doing - ;; it here is convienient, at least until we support - ;; cross-compilation. - 'installation-name - (string-append (version) - "-guix" - (match (system-type 'gc) - ['cgc "-cgc"] - ;; workaround Guile reader/printer: - ['|3m| "-bc"] - [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] - [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) - (make-parent-directory* new-config-pth) - (call-with-output-file* - new-config-pth - (lambda (out) - (pretty-write config out)))))))) + (define-values [parent-layer prefix] + (command-line + #:once-each + [("--extra-foreign-lib-search-dirs") dir-list + "foreign library directories, as a list of strings in `read` syntax" + (set! extra-foreign-lib-search-dirs + (call-with-input-string dir-list read))] + #:args (parent-layer prefix) + (values parent-layer prefix))) + (let* ([config + (for/fold + ([config (file->value (build-path parent-layer + config-file-pth))]) + ([spec (in-list + '((lib-dir lib-search-dirs "lib/racket") + (share-dir share-search-dirs "share/racket") + (links-file + links-search-files + "share/racket/links.rktd") + (pkgs-dir pkgs-search-dirs "share/racket/pkgs") + (bin-dir bin-search-dirs "bin") + (man-dir man-search-dirs "share/man") + (doc-dir doc-search-dirs "share/doc/racket") + (include-dir + include-search-dirs + "include/racket")))]) + (match-define (list main-key search-key pth) spec) + (hash-set* + config + main-key + (build-path-string prefix pth) + search-key + (list* #f + (hash-ref config + main-key + (build-path-string parent-layer pth)) + (filter values (hash-ref config search-key null)))))] + [config + (hash-update config + 'lib-search-dirs + (lambda (dirs) + ;; add after other layers, but before older + ;; foreign lib search directories + (define-values [rkt old-foreign-dirs] + (partition (lambda (pth) + (or (not pth) + (regexp-match? rx:racket pth))) + dirs)) + (append rkt + extra-foreign-lib-search-dirs + old-foreign-dirs)))] + [config + (hash-set* config + 'apps-dir + (build-path-string prefix "share/applications") + 'absolute-installation? #t + ;; Let Guix coexist with other installation + ;; methods without clobbering user-specific packages. + ;; This could be set in various places, but doing + ;; it here is convienient, at least until we support + ;; cross-compilation. + 'installation-name + (string-append (version) + "-guix" + (match (system-type 'gc) + ['cgc "-cgc"] + ;; workaround Guile reader/printer: + ['|3m| "-bc"] + [_ ""])))] + [bin-dir + (hash-ref config 'bin-dir)] + [config + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [new-config-pth + (build-path prefix config-file-pth)]) + (make-parent-directory* new-config-pth) + (call-with-output-file* + new-config-pth + (lambda (out) + (pretty-write config out))))))) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 10/24] gnu: racket-minimal: Separate from the Racket VM. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (8 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath ` (14 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes For consistency with other Racket distributions, 'racket-minimal' should have the "racket-lib" Racket package installed: see <https://github.com/racket/racket/issues/3851#issuecomment-942368947>. Happily, this gives us a clean boundary between the core Racket VM and compiler, with all of the bootstrapping involved, and building Racket packages and installation layers, which can be handled in a nice, uniform way and eventually turned into a 'racket-build-system'. Building the VM layer as an "in-place" installation should help us use it with other Racket tools. * gnu/packages/racket.scm (racket-vm-common-configure-flags): Add "--enable-origtree". Adapt "--enable-racket=" for "opt/racket-vm/" prefix. (racket-minimal-bc-cgc): Rename to ... (racket-vm-cgc): ... this new variable. [inputs]: Move 'openssl' and 'sqlite' to new 'racket-minimal'. [arguments]<#:strip-directories>: Use "opt/racket-vm/" prefix. <#:phases>: Wrap 'configure', 'patch-shebangs', 'validate-runpath', 'make-dynamic-linker-cache', and 'patch-dot-desktop-files' to use "opt/racket-vm/" prefix. Adapt 'initialize-config.rktd' for removal of 'openssl' and 'sqlite'. [description]: Tweak. (racket-minimal-bc-3m): Rename to ... (racket-vm-bc): ... this new variable. [synopsis, description]: Tweak. (racket-vm-cs): New variable, adapted from the old 'racket-minimal'. (chez-scheme-for-racket-bootstrap-bootfiles)[arguments]<#:phhases>: Adapt to the "opt/racket-vm/" prefix. (racket-minimal): Rewrite like 'racket' using 'racket-vm-cs'. (racket): Inherit from 'racket-minimal'. [inputs]: Add 'racket-vm-cs'. Move "racket-lib" and "base" to 'racket-minimal'. [arguments]<#:make-flags, #:configure-flags>: Override from 'racket-minimal'. (configure-layer.rkt): Adapt to support in-place VM build with possible intermediate layer. --- gnu/packages/racket.scm | 599 ++++++++++++++++++++++++++-------------- 1 file changed, 386 insertions(+), 213 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 3877837d38..d3d3eb2bbd 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -54,7 +54,91 @@ (define-module (gnu packages racket) ;; Commentary: ;; -;; Here's how bootstrapping minimal Racket works: +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository (<https://github.com/racket/racket>) is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. <https://github.com/pycket/pycket>.) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: ;; ;; - Racket BC [CGC] can be built with only a C compiler (except for ;; one caveat discussed below). @@ -72,6 +156,10 @@ (define-module (gnu packages racket) ;; ;; So, we build CGC to build 3M to build bootfiles and CS. ;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; ;; One remaining bootstrapping limitation is that Racket's reader, module ;; system, and macro expander are implemented in Racket. For Racket CS, ;; they are compiled to R6RS libraries as discussed above. This note from the @@ -145,14 +233,15 @@ (define (racket-vm-common-configure-flags) '())) ,@(cond ((false-if-exception - (search-input-file %build-inputs "/bin/racket")) + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) => (lambda (racket) (list (string-append "--enable-racket=" racket)))) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" #$(file-append bash-minimal "/bin/sh")) - "--disable-strip")) + "--disable-strip" + "--enable-origtree")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -173,31 +262,25 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal-bc-cgc +(define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. (hidden-package (package - (name "racket-minimal-bc-cgc") + (name "racket-vm-cgc") (version %racket-version) (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants (native-inputs (list libtool)) ;; <- only for BC variants (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main ;; distribution. @@ -208,51 +291,72 @@ (define-public racket-minimal-bc-cgc (ice-9 regex) (guix build gnu-build-system) (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see <https://github.com/racket/racket/issues/3851>. - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) (home-page "https://racket-lang.org") (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or @@ -262,32 +366,33 @@ (define maybe-release-catalog scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the Racket CS implementation. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-3m +(define-public racket-vm-bc (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") + (inherit racket-vm-cgc) + (name "racket-vm-bc") (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + (substitute-keyword-arguments (package-arguments racket-vm-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") + (synopsis "Racket BC [3M] implementation") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'').") @@ -295,23 +400,23 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat)))) -(define-public racket-minimal +(define-public racket-vm-cs (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal") + (inherit racket-vm-bc) + (name "racket-vm-cs") (inputs - (modify-inputs (package-inputs racket-minimal-bc-cgc) + (modify-inputs (package-inputs racket-vm-cgc) (prepend zlib lz4) (delete "libffi"))) (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m))) + racket-vm-bc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:phases bc-phases) - #~(modify-phases #$bc-phases + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" @@ -328,17 +433,14 @@ (define-public racket-minimal "--enable-libz" "--enable-lz4" #$(racket-vm-common-configure-flags))))) - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") - (properties `()) +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) @@ -353,7 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source %racket-origin) (inputs `()) - (native-inputs (list racket-minimal-bc-3m)) + (native-inputs (list racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -371,7 +473,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) - "/bin/racket") + "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, @@ -452,10 +554,116 @@ (define (simple-racket-origin repo hash specs) %racket-version))) specs)) +(define-public racket-minimal + (package + (name "racket-minimal") + (version %racket-version) + (source #f) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs + (list openssl + sqlite + racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-packages-origin + "base" %racket-origin + '(("base" "pkgs/base") + ("racket-lib" "pkgs/racket-lib"))))) + (build-system gnu-build-system) + (arguments + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `configure-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install`. + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format + #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$configure-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. + +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + (define-public racket (package + (inherit racket-minimal) (name "racket") - (version %racket-version) (source #f) (inputs (list @@ -474,6 +682,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer + racket-vm-cs ;; TODO (racket-vm-for-system) (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") '("2d" "2d-doc" "2d-lib")) @@ -482,9 +691,7 @@ (define-public racket '(("algol60" "."))) (racket-packages-origin "racket" %racket-origin - '(("base" "pkgs/base") ;; FIXME belongs in racket-minimal - ("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal - ("at-exp-lib" "pkgs/at-exp-lib") + '(("at-exp-lib" "pkgs/at-exp-lib") ("compiler" "pkgs/compiler") ("compiler-lib" "pkgs/compiler-lib") ("net" "pkgs/net") @@ -808,91 +1015,39 @@ (define-public racket '("xrepl" "xrepl-doc" "xrepl-lib")))) (build-system gnu-build-system) (arguments - ;; We're using #:configure-flags to pass flags for - ;; `configure-layer.rkt` and #:make-flags to pass arguments for - ;; `raco pkg install`. - (list - #:configure-flags - #~`("--extra-foreign-lib-search-dirs" - ,(format #f "~s" - '(#$@(map (lambda (name) - (cond - ((this-package-input name) - => (cut file-append <> "/lib")) - (else - (raise-exception - (make-exception - (make-assertion-failure) - (make-exception-with-message - "missing input to the 'racket' package") - (make-exception-with-irritants - (list name))))))) - '("cairo" - "fontconfig-minimal" ;; aka fontconfig - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg-turbo" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))))) - #:make-flags #~`("main-distribution") - #:tests? #f ;; packaged separately - #:modules '((guix build gnu-build-system) - (guix build utils) - (guix build union) - (ice-9 match)) - #:imported-modules `((guix build union) - ,@%gnu-build-system-modules) - #:phases - #~(modify-phases %standard-phases - (delete 'unpack) - (replace 'configure - (lambda* (#:key inputs configure-flags #:allow-other-keys) - (let* ((racket (search-input-file inputs "bin/racket"))) - (apply invoke - racket - #$configure-layer.rkt - `(,@configure-flags - ,(dirname (dirname racket)) - ,#$output)) - (invoke racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" "setup" - "--no-user")))) - (replace 'build - (lambda* (#:key inputs #:allow-other-keys) - ;; We use "share/racket/pkgs" for sources to distinguish them - ;; from the "lib/racket/pkgs" of a potential parent layer. - (union-build (string-append #$output "/lib/racket/pkgs") - (search-path-as-list '("share/racket/pkgs") - (map cdr inputs)) - #:create-all-directories? #t))) - (replace 'install - (lambda* (#:key inputs make-flags #:allow-other-keys) - (let ((racket (search-input-file inputs "/bin/racket"))) - (unless (null? make-flags) - (invoke racket - "-l-" - "pkg/dirs-catalog" - "--link" - "local-catalog" - (string-append #$output "/lib/racket/pkgs")) - (apply invoke - racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" - "pkg" "install" - "--installation" - "--auto" - "--catalog" "local-catalog" - make-flags)))))))) - (home-page "https://racket-lang.org") + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -902,10 +1057,7 @@ (define-public racket The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) (define configure-layer.rkt (scheme-file @@ -918,41 +1070,53 @@ (define configure-layer.rkt racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define tethered? #f) + (define parent #f) (define extra-foreign-lib-search-dirs '()) - (define-values [parent-layer prefix] + (define-values [vm-dir prefix] (command-line #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] [("--extra-foreign-lib-search-dirs") dir-list "foreign library directories, as a list of strings in `read` syntax" (set! extra-foreign-lib-search-dirs (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (values parent-layer prefix))) + #:args (vm-dir prefix) + (values vm-dir prefix))) (let* ([config (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) (hash-set* config main-key @@ -961,7 +1125,10 @@ (define-values [parent-layer prefix] (list* #f (hash-ref config main-key - (build-path-string parent-layer pth)) + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) (filter values (hash-ref config search-key null)))))] [config (hash-update config @@ -995,15 +1162,21 @@ (define-values [rkt old-foreign-dirs] ;; workaround Guile reader/printer: ['|3m| "-bc"] [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) (make-parent-directory* new-config-pth) (call-with-output-file* new-config-pth -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez). 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (9 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath ` (13 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (chez-scheme-for-racket-bootstrap-bootfiles): Move to ... * gnu/packages/chez.scm (chez-scheme-for-racket-bootstrap-bootfiles): ... this new variable. [source]: Avoid problematic cycle with "racket.scm". [arguments]<#:phases>: Likewise. --- gnu/packages/chez.scm | 62 +++++++++++++++++++++++++++++++++++++++++ gnu/packages/racket.scm | 52 ---------------------------------- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 47904e7b4e..046bb3dcdc 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -31,12 +31,14 @@ (define-module (gnu packages chez) #:use-module (guix git-download) #:use-module (guix utils) #:use-module (guix gexp) + #:use-module (guix build-system copy) #:use-module (guix build-system gnu) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) #:use-module (gnu packages linux) #:use-module (gnu packages netpbm) + #:use-module (gnu packages racket) #:use-module (gnu packages tex) #:use-module (gnu packages compression) #:use-module (gnu packages image) @@ -260,6 +262,66 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket-bootstrap-bootfiles + (package + (name "chez-scheme-for-racket-bootstrap-bootfiles") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs `()) + (native-inputs (list racket-vm-bc)) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list + #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")) + #:phases + #~(let ((unpack (assoc-ref %standard-phases 'unpack))) + (modify-phases %standard-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + (copy-recursively + #$nanopass + "nanopass" + #:keep-mtime? #t))) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt"))))))) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Chez Scheme bootfiles bootstrapped by Racket") + (description "Chez Scheme is a self-hosting compiler: building it +requires ``bootfiles'' containing the Scheme-implemented portions compiled for +the current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +The Racket package @code{cs-bootstrap} (part of the main Racket Git +repository) implements enough of a Chez Scheme simulation to load the Chez +Scheme compiler purely from source into Racket and apply the compiler to +itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as +long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket +7.1 and later, including the Racket BC variant. + +Note that the generated bootfiles are specific to Racket's fork of Chez +Scheme, and @code{cs-bootstrap} does not currently support building upstream +Chez Scheme.") + (license (list asl2.0)))) + (define-public chez-srfi (package (name "chez-srfi") diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index d3d3eb2bbd..a853e520f5 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -445,58 +445,6 @@ (define-public racket-vm-cs ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) -(define-public chez-scheme-for-racket-bootstrap-bootfiles - (package - (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. - (source %racket-origin) - (inputs `()) - (native-inputs (list racket-vm-bc)) - (build-system copy-build-system) - ;; TODO: cross compilation - (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(modify-phases %standard-phases - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$(make-unpack-nanopass+stex))) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt")))))) - (home-page "https://github.com/racket/ChezScheme") - ;; ^ This is downstream of https://github.com/racket/racket, - ;; but it's designed to be a friendly landing place for people - ;; who want a ChezScheme-shaped repositroy. - (synopsis "Chez Scheme bootfiles bootstrapped by Racket") - (description "Chez Scheme is a self-hosting compiler: building it -requires ``bootfiles'' containing the Scheme-implemented portions compiled for -the current platform. (Chez can then cross-compile bootfiles for all other -supported platforms.) - -The Racket package @code{cs-bootstrap} (part of the main Racket Git -repository) implements enough of a Chez Scheme simulation to load the Chez -Scheme compiler purely from source into Racket and apply the compiler to -itself, thus bootstrapping Chez Scheme. Bootstrapping takes about 10 times as -long as using an existing Chez Scheme, but @code{cs-bootstrap} supports Racket -7.1 and later, including the Racket BC variant. - -Note that the generated bootfiles are specific to Racket's fork of Chez -Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list license:asl2.0)))) - (define (racket-packages-origin name origin specs) "Extract from ORIGIN the sources for the Racket packages specified by SPECS, a non-empty list of package specifications. In the resulting file-like -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 12/24] gnu: chez: Add utilities for Chez machine types. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (10 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath ` (12 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-machine->nonthreaded, chez-machine->threaded, chez-machine->nix-system, nix-system->chez-machine, chez-upstream-features-for-system): New functions. (%nix-arch-to-chez-alist, %nix-os-to-chez-alist): New private constants. (chez-scheme)[supported-systems]: Compute based on 'nix-system->chez-machine' and 'chez-upstream-features-for-system'. (chez-scheme-for-racket-bootstrap-bootfiles)[supported-systems]: Compute based on 'nix-system->chez-machine'. --- gnu/packages/chez.scm | 127 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 046bb3dcdc..603fc4201e 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -44,7 +44,119 @@ (define-module (gnu packages chez) #:use-module (gnu packages image) #:use-module (gnu packages xorg) #:use-module (ice-9 match) - #:use-module (srfi srfi-1)) + #:use-module (srfi srfi-1) + #:export (nix-system->chez-machine + chez-machine->nonthreaded + chez-machine->threaded)) + +(define (chez-machine->nonthreaded machine) + "Given a string MACHINE naming a Chez Scheme machine type, returns a string +naming the nonthreaded machine type for the same architecture and OS as +MACHINE. The returned string may share storage with MACHINE." + ;; Chez Scheme documentation consistently uses "nonthreaded" rather than + ;; e.g. "unthreaded" + (if (eqv? #\t (string-ref machine 0)) + (substring machine 1) + machine)) +(define (chez-machine->threaded machine) + "Like @code{chez-machine->nonthreaded}, but returns the threaded machine +type." + (if (eqv? #\t (string-ref machine 0)) + machine + (string-append "t" machine))) + +;; Based on the implementation from raco-cross-lib/private/cross/platform.rkt +;; in https://github.com/racket/raco-cross. +;; For supported platforms, refer to release_notes/release_notes.stex in the +;; upstream Chez Scheme repository or to racket/src/ChezScheme/README.md +;; in https://github.com/racket/racket. +(define %nix-arch-to-chez-alist + `(("x86_64" . "a6") + ("i386" . "i3") + ("aarch64" . "arm64") + ("armhf" . "arm32") ;; Chez supports ARM v6+ + ("ppc" . "ppc32"))) +(define %nix-os-to-chez-alist + `(("w64-mingw32" . "nt") + ("darwin" . "osx") + ("linux" . "le") + ("freebsd" . "fb") + ("openbsd" . "ob") + ("netbsd" . "nb") + ("solaris" . "s2"))) + +(define (chez-machine->nix-system machine) + "Return the Nix system type corresponding to the Chez Scheme machine type +MACHINE. If MACHINE is not a string representing a known machine type, an +exception is raised. This function does not distinguish between threaded and +nonthreaded variants of MACHINE. + +Note that this function only handles Chez Scheme machine types in the +strictest sense, not other kinds of descriptors sometimes used in place of a +Chez Scheme machine type by Racket, such as @code{\"pb\"}, @code{#f}, or +@code{\"racket\"}. (When using such extensions, the Chez Scheme machine type +for the host system is often still relevant.)" + (let ((machine (chez-machine->nonthreaded machine))) + (let find-arch ((alist %nix-arch-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (string-prefix? chez machine) + (string-append + nix "-" (let ((machine-os + (substring machine (string-length chez)))) + (let find-os ((alist %nix-os-to-chez-alist)) + (match alist + (((nix . chez) . alist) + (if (equal? chez machine-os) + nix + (find-os alist))))))) + (find-arch alist))))))) + +(define* (nix-system->chez-machine #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return the Chez Scheme machine type corresponding to the Nix system +identifier SYSTEM, or @code{#f} if the translation of SYSTEM to a Chez Scheme +machine type is undefined. + +It is unspecified whether the resulting string will name a threaded or a +nonthreaded machine type: when the distinction is relevant, use +@code{chez-machine->nonthreaded} or @code{chez-machine->threaded} to adjust +the result." + (let* ((hyphen (string-index system #\-)) + (nix-arch (substring system 0 hyphen)) + (nix-os (substring system (+ 1 hyphen))) + (chez-arch (assoc-ref %nix-arch-to-chez-alist nix-arch)) + (chez-os (assoc-ref %nix-os-to-chez-alist nix-os))) + (and chez-arch chez-os (string-append chez-arch chez-os)))) + +(define* (chez-upstream-features-for-system #:optional + (system + (or (%current-target-system) + (%current-system)))) + "Return a list of symbols naming features supported by upstream Chez Scheme +for the Nix system identifier SYSTEM, or @code{#f} if upstream Chez Scheme +does not support SYSTEM at all. + +If native threads are supported, the returned list will include +@code{'threads}. Other feature symbols may be added in the future." + (cond + ((not (nix-system->chez-machine system)) + #f) + ((target-aarch64? system) + #f) + ((target-arm32? system) + (and (target-linux? system) + '())) + ((target-ppc32? system) + (and (target-linux? system) + '(threads))) + (else + '(threads)))) + +;; +;; Chez Scheme: +;; (define nanopass (let ((version "1.9.2")) @@ -251,8 +363,11 @@ (define* (stex-make #:optional (suffix "")) ;; We should too. It is the Chez machine type arm32le ;; (no threaded version upstream yet, though there is in ;; Racket's fork), more specifically (per the release notes) ARMv6. - (supported-systems (fold delete %supported-systems - '("mips64el-linux" "armhf-linux"))) + (supported-systems + (delete + "armhf-linux" ;; <-- should work, but reportedly broken + (filter chez-upstream-features-for-system + %supported-systems))) (home-page "https://cisco.github.io/ChezScheme/") (synopsis "R6RS Scheme compiler and run-time") (description @@ -300,6 +415,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt"))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people @@ -322,6 +439,10 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Chez Scheme.") (license (list asl2.0)))) +;; +;; Packages: +;; + (define-public chez-srfi (package (name "chez-srfi") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 13/24] gnu: racket: Add 'racket-vm-for-system'. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (11 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath ` (11 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-vm-for-system): New procedure. (racket-minimal, racket)[inputs]: Use it. --- gnu/packages/racket.scm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index a853e520f5..272638ca2e 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -187,6 +187,14 @@ (define-module (gnu packages racket) ;; ;; Code: +(define* (racket-vm-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'racket-vm-cs' if it supports SYSTEM; 'racket-vm-bc' otherwise." + (if (nix-system->chez-machine system) + racket-vm-cs + racket-vm-bc)) + (define %racket-version "8.4") ;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! (define %racket-commit @@ -513,7 +521,7 @@ (define-public racket-minimal (inputs (list openssl sqlite - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (racket-packages-origin "base" %racket-origin '(("base" "pkgs/base") @@ -630,7 +638,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer - racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-vm-for-system) (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") '("2d" "2d-doc" "2d-lib")) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 14/24] gnu: chez-scheme: Use new style for Chez packages. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (12 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath ` (10 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-configure, chez-make-flags): Use G-expressions. (chez-srfi)[arguments]: Use G-expressions, 'chez-configure', and 'chez-make-flags'. (chez-web, chez-sockets)[native-inputs]: Remove labels. [arguments]: Use G-expressions. (chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils)[arguments]: Use G-expressions. --- gnu/packages/chez.scm | 382 ++++++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 186 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 603fc4201e..4ee9711bb4 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -443,6 +443,27 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; Packages: ;; +;; Help function for Chez Scheme to add the current path to +;; CHEZSCHEMELIBDIRS. +(define chez-configure + #~(lambda _ + (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) + (setenv "CHEZSCHEMELIBDIRS" + (if chez-env + (string-append ".:" chez-env) + "."))))) + +;; Help function to define make flags for some Chez Scheme custom make +;; files. +(define (chez-make-flags name version) + #~(let ((out #$output)) + (list + ;; Set 'chezversion' so that libraries are installed in + ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. + (string-append "chezversion=" #$(package-version chez-scheme)) + (string-append "PREFIX=" out) + (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) + (define-public chez-srfi (package (name "chez-srfi") @@ -460,13 +481,11 @@ (define-public chez-srfi (native-inputs (list chez-scheme)) (arguments - `(#:make-flags (let ((out (assoc-ref %outputs "out"))) - (list (string-append "PREFIX=" out) - "CHEZ=chez-scheme --libdirs ./" - (string-append "chezversion=" ,(package-version chez-scheme)))) - #:test-target "test" - #:phases (modify-phases %standard-phases - (delete 'configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-srfi") (synopsis "SRFI libraries for Chez Scheme") (description @@ -491,42 +510,48 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("ghostscript" ,ghostscript) - ("texlive" ,(texlive-updmap.cfg (list texlive-oberdiek - texlive-epsf - texlive-metapost - texlive-charter - texlive-pdftex - texlive-context - texlive-cm - texlive-tex-plain))))) + (list chez-scheme + ghostscript + ;; FIXME: This package fails to build with the error: + ;; mktexpk: don't know how to create bitmap font for bchr8r + ;; Replacing the following with `texlive` fixes it. + ;; What is missing? + (texlive-updmap.cfg (list texlive-oberdiek + texlive-epsf + texlive-metapost + texlive-charter + texlive-pdftex + texlive-context + texlive-cm + texlive-tex-plain)))) (arguments - `(#:make-flags (list (string-append "PREFIX=" %output) - (string-append "DOCDIR=" %output "/share/doc/" - ,name "-" ,version) - (string-append "LIBDIR=" %output "/lib/chezweb") - (string-append "TEXDIR=" %output "/share/texmf-local")) - #:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - ;; This package has a custom "bootstrap" script that - ;; is meant to be run from the Makefile. - (delete 'bootstrap) - (replace 'configure - (lambda* _ - (copy-file "config.mk.template" "config.mk") - (substitute* "tangleit" - (("\\./cheztangle\\.ss" all) - (string-append "chez-scheme --program " all))) - (substitute* "weaveit" - (("mpost chezweb\\.mp") - "mpost --tex=tex chezweb.mp") - (("\\./chezweave" all) - (string-append "chez-scheme --program " all))) - (substitute* "installit" - (("-g \\$GROUP -o \\$OWNER") "")) - #t))))) + (list + #:make-flags + #~(list (string-append "PREFIX=" #$output) + (string-append "DOCDIR=" #$output "/share/doc/" + #$name "-" #$version) + ;; lib/chez-scheme/chezweb ??? + (string-append "LIBDIR=" #$output "/lib/chezweb") + (string-append "TEXDIR=" #$output "/share/texmf-local")) + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + ;; This package has a custom "bootstrap" script that + ;; is meant to be run from the Makefile. + (delete 'bootstrap) + (replace 'configure + (lambda* _ + (copy-file "config.mk.template" "config.mk") + (substitute* "tangleit" + (("\\./cheztangle\\.ss" all) + (string-append "scheme --program " all))) + (substitute* "weaveit" + (("mpost chezweb\\.mp") + "mpost --tex=tex chezweb.mp") + (("\\./chezweave" all) + (string-append "scheme --program " all))) + (substitute* "installit" + (("-g \\$GROUP -o \\$OWNER") ""))))))) (home-page "https://github.com/arcfide/ChezWEB") (synopsis "Hygienic Literate Programming for Chez Scheme") (description "ChezWEB is a system for doing Knuthian style WEB @@ -550,95 +575,78 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - `(("chez-scheme" ,chez-scheme) - ("chez-web" ,chez-web) - ("texlive" ,(texlive-updmap.cfg (list texlive-pdftex))))) + (list chez-scheme + chez-web + (texlive-updmap.cfg (list texlive-pdftex)))) (arguments - `(#:tests? #f ; no tests - #:phases - (modify-phases %standard-phases - (replace 'configure - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-web (assoc-ref inputs "chez-web")) - (chez (assoc-ref inputs "chez-scheme")) - (chez-h (dirname (car (find-files chez "scheme\\.h"))))) - (substitute* "Makefile" - (("(SCHEMEH=).*$" all var) - (string-append var chez-h))) - #t))) - (add-before 'build 'tangle - (lambda* (#:key inputs #:allow-other-keys) - (setenv "TEXINPUTS" - (string-append - (getcwd) ":" - (assoc-ref inputs "chez-web") "/share/texmf-local/tex/generic:" - ":")) - ;; just using "make" tries to build the .c files before - ;; they are created. - (and (invoke "make" "sockets") - (invoke "make")))) - (replace 'build - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) - "-site/arcfide"))) - ;; make sure Chez Scheme can find the shared libraries. - (substitute* "sockets.ss" - (("(load-shared-object) \"(socket-ffi-values\\.[sd][oy].*)\"" - all cmd so) - (string-append cmd " \"" chez-site "/" so "\"")) - (("sockets-stub\\.[sd][oy].*" all) - (string-append chez-site "/" all))) - ;; to compile chez-sockets, the .so files must be - ;; installed (because of the absolute path we - ;; inserted above). - (for-each (lambda (f d) (install-file f d)) - '("socket-ffi-values.so" "sockets-stub.so") - (list chez-site chez-site)) - (zero? (system "echo '(compile-file \"sockets.sls\")' | scheme -q"))))) - (replace 'install - (lambda* (#:key outputs inputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (lib (string-append out "/lib/chez-sockets")) - (doc (string-append out "/share/doc/" ,name "-" ,version)) - (chez-site (string-append out "/lib/csv" - ,(package-version chez-scheme) + (list + #:tests? #f ; no tests + #:phases + #~(modify-phases %standard-phases + (replace 'configure + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (let* ((scheme (search-input-file (or native-inputs inputs) + "/bin/scheme")) + (lib (string-append (dirname scheme) "/../lib")) + (header-file (car (find-files lib "scheme\\.h"))) + (include-dir (dirname header-file))) + (substitute* "Makefile" + (("(SCHEMEH=).*$" _ var) + (string-append var include-dir)))))) + (add-before 'build 'tangle + (lambda* (#:key inputs #:allow-other-keys) + (setenv "TEXINPUTS" + (string-append + (getcwd) ":" + (assoc-ref inputs "chez-web") + "/share/texmf-local/tex/generic:" + ":")) + ;; just using "make" tries to build the .c files before + ;; they are created. + (and (invoke "make" "sockets") + (invoke "make")))) + (replace 'build + (lambda args + (let ((chez-site (string-append #$output + "/lib/csv" + (package-version chez-scheme) "-site/arcfide"))) - (for-each (lambda (f d) (install-file f d)) - '("sockets.pdf" "sockets.so") - (list doc chez-site)) - #t)))))) + ;; make sure Chez Scheme can find the shared libraries. + (substitute* "sockets.ss" + (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post)) + (("(\")(sockets-stub\\.[sd][oy][^\"]*)(\")" + _ pre file post) + (string-append pre chez-site "/" file post))) + ;; to compile chez-sockets, the .so files must be + ;; installed (because of the absolute path we + ;; inserted above). + (for-each (lambda (f) + (install-file f chez-site)) + '("socket-ffi-values.so" + "sockets-stub.so")) + (invoke "bash" + "-c" + (format #f "echo '~s' | scheme -q" + '(compile-file "sockets.sls")))))) + (replace 'install + (lambda args + (install-file "sockets.so" + (string-append #$output + "/lib/csv" + #$(package-version chez-scheme) + "-site/arcfide")) + (install-file "sockets.pdf" + (string-append #$output + "/share/doc/" + #$name "-" #$version))))))) (home-page "https://github.com/arcfide/chez-sockets") (synopsis "Extensible sockets library for Chez Scheme") (description "Chez-sockets is an extensible sockets library for Chez Scheme.") (license expat)))) -;; Help function for Chez Scheme to add the current path to -;; CHEZSCHEMELIBDIRS. -(define chez-configure - '(lambda _ - (let ((chez-env (getenv "CHEZSCHEMELIBDIRS"))) - (setenv "CHEZSCHEMELIBDIRS" - (if chez-env - (string-append ".:" chez-env) - ".")) - #t))) - -;; Help function to define make flags for some Chez Scheme custom make -;; files. -(define (chez-make-flags name version) - `(let ((out (assoc-ref %outputs "out"))) - (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" ,(package-version chez-scheme)) - (string-append "PREFIX=" out) - (string-append "DOCDIR=" out "/share/doc/" - ,name "-" ,version)))) - (define-public chez-matchable (package (name "chez-matchable") @@ -659,10 +667,11 @@ (define-public chez-matchable (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "Portable hygienic pattern matcher for Scheme") (description "This package provides a superset of the popular Scheme @code{match} package by Andrew Wright, written in fully portable @@ -690,10 +699,11 @@ (define-public chez-irregex (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (home-page "https://github.com/fedeinthemix/chez-irregex") (synopsis "Portable regular expression library for Scheme") (description "This package provides a portable and efficient @@ -720,17 +730,18 @@ (define-public chez-fmt (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "chez-check" - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - (replace 'build - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-build" make-flags))) - (replace 'install - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "chez-install" make-flags)))))) + (list #:make-flags (chez-make-flags name version) + #:test-target "chez-check" + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + (replace 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-build" make-flags))) + (replace 'install + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "chez-install" make-flags)))))) (home-page "http://synthcode.com/scheme/fmt") (synopsis "Combinator formatting library for Chez Scheme") (description "This package provides a library of procedures for @@ -760,10 +771,11 @@ (define-public chez-mit (native-inputs (list chez-scheme)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:test-target "test" - #:phases (modify-phases %standard-phases - (replace 'configure ,chez-configure)))) + (list #:make-flags (chez-make-flags name version) + #:test-target "test" + #:phases #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure)))) (synopsis "MIT/GNU Scheme compatibility library for Chez Scheme") (description "This package provides a set of MIT/GNU Scheme compatibility libraries for Chez Scheme. The main goal was to provide the functionality @@ -792,46 +804,44 @@ (define-public chez-scmutils (propagated-inputs (list chez-mit chez-srfi)) (arguments - `(#:make-flags ,(chez-make-flags name version) - #:tests? #f ; no test suite - #:phases - (modify-phases %standard-phases - (replace 'configure ,chez-configure) - ;; Since the documentation is lacking, we install the source - ;; code. For things to work correctly we have to replace - ;; relative paths by absolute ones in 'include' forms. This - ;; in turn requires us to compile the files in the final - ;; destination. - (delete 'build) - (add-after 'install 'install-src - (lambda* (#:key (make-flags '()) #:allow-other-keys) - (apply invoke "make" "install-src" make-flags))) - (add-after 'install-src 'absolute-path-in-scm-files - (lambda* (#:key outputs #:allow-other-keys) - (let ((out (assoc-ref outputs "out"))) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils") - (string-append "include \"" (dirname file))))) - (find-files out "\\.sls")) - (for-each (lambda (file) - (substitute* file - (("include +\"\\./scmutils/simplify") - (string-append "include \"" (dirname file))))) - (find-files out "fbe-syntax\\.scm")) - #t))) - (add-after 'absolute-path-in-scm-files 'build - (lambda* (#:key outputs (make-flags '()) #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (mk-file (car (find-files out "Makefile")))) - (with-directory-excursion (dirname mk-file) - (apply invoke "make" "build" make-flags))))) - (add-after 'build 'clean-up - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out"))) - (for-each delete-file - (find-files out "Makefile|compile-all\\.ss")) - #t)))))) + (list + #:make-flags (chez-make-flags name version) + #:tests? #f ; no test suite + #:phases + #~(modify-phases %standard-phases + (replace 'configure + #$chez-configure) + ;; Since the documentation is lacking, we install the source + ;; code. For things to work correctly we have to replace + ;; relative paths by absolute ones in 'include' forms. This + ;; in turn requires us to compile the files in the final + ;; destination. + (delete 'build) + (add-after 'install 'install-src + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (apply invoke "make" "install-src" make-flags))) + (add-after 'install-src 'absolute-path-in-scm-files + (lambda* (#:key #:allow-other-keys) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils") + (string-append "include \"" (dirname file))))) + (find-files #$output "\\.sls")) + (for-each (lambda (file) + (substitute* file + (("include +\"\\./scmutils/simplify") + (string-append "include \"" (dirname file))))) + (find-files #$output "fbe-syntax\\.scm")))) + (add-after 'absolute-path-in-scm-files 'build + (lambda* (#:key (make-flags '()) #:allow-other-keys) + (let ((mk-file (car (find-files #$output "Makefile")))) + (with-directory-excursion (dirname mk-file) + (apply invoke "make" "build" make-flags))))) + (add-after 'build 'clean-up + (lambda args + (for-each delete-file + (find-files #$output + "Makefile|compile-all\\.ss"))))))) (synopsis "Port of MIT/GNU Scheme Scmutils to Chez Scheme") (description "This package provides a port of the MIT/GNU Scheme Scmutils program to Chez Scheme. The port consists of a set of -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (13 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath ` (9 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes There does not seem to be any widely accepted standard path to use for "CHEZSCHEMELIBDIRS". Using a path without a version number in it avoids having to compute the actual path everywhere, which would be especially unpleasant when support is added for the Racket variant of Chez Scheme, which always has a different version number than upstream. * gnu/packages/chez.scm (chez-scheme)[native-search-paths]: Change to use "lib/chez-scheme" instead of "lib/csvX.Y.Z-site" for "CHEZSCHEMELIBDIRS". (chez-make-flags): Update accordingly. (chez-sockets)[arguments]<#:phases>: Likewise. --- gnu/packages/chez.scm | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 4ee9711bb4..f4c87fbcf7 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -233,7 +233,7 @@ (define-public chez-scheme (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") - (files (list (string-append "lib/csv" version "-site")))))) + (files '("lib/chez-scheme"))))) (outputs '("out" "doc")) (arguments `(#:modules @@ -458,9 +458,9 @@ (define chez-configure (define (chez-make-flags name version) #~(let ((out #$output)) (list - ;; Set 'chezversion' so that libraries are installed in - ;; 'lib/csvX.Y.Z-site' like Chez's 'native-search-paths' expects. - (string-append "chezversion=" #$(package-version chez-scheme)) + ;; Set 'schemedir' so that libraries are installed in + ;; 'lib/chez-scheme' like Chez's 'native-search-paths' expects. + (string-append "schemedir=" out "/lib/chez-scheme") (string-append "PREFIX=" out) (string-append "DOCDIR=" out "/share/doc/" #$name "-" #$version)))) @@ -608,9 +608,7 @@ (define-public chez-sockets (replace 'build (lambda args (let ((chez-site (string-append #$output - "/lib/csv" - (package-version chez-scheme) - "-site/arcfide"))) + "/lib/chez-scheme/arcfide"))) ;; make sure Chez Scheme can find the shared libraries. (substitute* "sockets.ss" (("(object \")(socket-ffi-values\\.[sd][oy][^\"]*)(\")" @@ -634,9 +632,7 @@ (define-public chez-sockets (lambda args (install-file "sockets.so" (string-append #$output - "/lib/csv" - #$(package-version chez-scheme) - "-site/arcfide")) + "/lib/chez-scheme/arcfide")) (install-file "sockets.pdf" (string-append #$output "/share/doc/" -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 16/24] gnu: chez-scheme: Use shared zlib and lz4. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (14 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 17/24] gnu: chez-scheme: Use new package style Philip McGrath ` (8 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This change also involves building 'libkernel.a' instead of 'kernel.o'. Support for these build options was merged upstream in 2019: see discussion at <https://github.com/cisco/ChezScheme/pull/443>. * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove 'zlib:static' and 'lz4:static'. [arguments]: Adjust configure phase accordingly. --- gnu/packages/chez.scm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index f4c87fbcf7..dd40baa719 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -211,9 +211,7 @@ (define-public chez-scheme (inputs `(("libuuid" ,util-linux "lib") ("zlib" ,zlib) - ("zlib:static" ,zlib "static") ("lz4" ,lz4) - ("lz4:static" ,lz4 "static") ;; for expeditor: ("ncurses" ,ncurses) ;; for X11 clipboard support in expeditor: @@ -266,14 +264,14 @@ (define src (lz4-static (assoc-ref inputs "lz4:static")) (out (assoc-ref outputs "out")) ;; add flags which are always required: - (flags (cons* - (string-append "--installprefix=" out) - (string-append "ZLIB=" zlib-static "/lib/libz.a") - (string-append "LZ4=" lz4-static "/lib/liblz4.a") - ;; Guix will do compress man pages, - ;; and letting Chez try causes an error - "--nogzip-man-pages" - configure-flags))) + (flags (cons* (string-append "--installprefix=" out) + "ZLIB=-lz" + "LZ4=-llz4" + "--libkernel" + ;; Guix will do compress-man-pages, + ;; and letting Chez try causes an error + "--nogzip-man-pages" + configure-flags))) (format #t "configure flags: ~s~%" flags) ;; Some makefiles (for tests) don't seem to propagate CC ;; properly, so we take it out of their hands: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 17/24] gnu: chez-scheme: Use new package style. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (15 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 18/24] gnu: Add stex Philip McGrath ` (7 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-scheme)[inputs]: Remove labels. [native-inputs]: Likewise. [arguments]: Use G-expressions. <#:phases>: Use 'search-input-file' instead of 'assoc-ref'. (nanopass): Make public as a temporary workaround for Racket. * gnu/packages/racket.scm (make-unpack-nanopass+stex): Update accordingly. --- gnu/packages/chez.scm | 286 +++++++++++++++++++--------------------- gnu/packages/racket.scm | 5 +- 2 files changed, 135 insertions(+), 156 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index dd40baa719..ad263a8fe3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -158,7 +158,7 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define nanopass +(define-public nanopass (let ((version "1.9.2")) (origin (method git-fetch) @@ -185,86 +185,80 @@ (define stex (define-public chez-scheme (package (name "chez-scheme") + ;; The version should match `(scheme-version-number)`. + ;; See s/cmacros.ss c. line 360. (version "9.5.6") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/cisco/ChezScheme") - (commit (string-append "v" version)))) - (sha256 - (base32 "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) - (file-name (git-file-name name version)) - (snippet - ;; Remove bundled libraries. - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (for-each (lambda (dir) - (when (directory-exists? dir) - (delete-file-recursively dir))) - '("stex" - "nanopass" - "lz4" - "zlib"))))))) + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/cisco/ChezScheme") + (commit (string-append "v" version)))) + (sha256 + (base32 + "07s433hn1z2slfc026sidrpzxv3a8narcd40qqr1xrpb9012xdky")) + (file-name (git-file-name name version)) + (snippet #~(begin + (use-modules (guix build utils)) + (for-each (lambda (dir) + (when (directory-exists? dir) + (delete-file-recursively dir))) + '("stex" + "nanopass" + "lz4" + "zlib")))))) (build-system gnu-build-system) (inputs - `(("libuuid" ,util-linux "lib") - ("zlib" ,zlib) - ("lz4" ,lz4) - ;; for expeditor: - ("ncurses" ,ncurses) - ;; for X11 clipboard support in expeditor: - ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 - ("libx11" ,libx11))) + (list + `(,util-linux "lib") ;<-- libuuid + zlib + lz4 + ncurses ;<-- for expeditor + ;; for X11 clipboard support in expeditor: + ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 + libx11)) (native-inputs - `(("nanopass" ,nanopass) ; source only - ;; for docs - ("stex" ,stex) - ("xorg-rgb" ,xorg-rgb) - ("texlive" ,(texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek))) - ("ghostscript" ,ghostscript) - ("netpbm" ,netpbm))) + (list nanopass ; source only + ;; for docs + stex + xorg-rgb + (texlive-updmap.cfg (list texlive-dvips-l3backend + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") (files '("lib/chez-scheme"))))) (outputs '("out" "doc")) (arguments - `(#:modules - ((guix build gnu-build-system) + (list + #:modules + '((guix build gnu-build-system) (guix build utils) (ice-9 ftw) (ice-9 match)) - #:test-target "test" - #:configure-flags - '("--threads") ;; TODO when we fix armhf, it doesn't support --threads - #:phases - (modify-phases %standard-phases - ;; put these where configure expects them to be - (add-after 'unpack 'unpack-nanopass+stex - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (for-each (lambda (dep) - (define src - (assoc-ref (or native-inputs inputs) dep)) - (copy-recursively src dep - #:keep-mtime? #t)) - '("nanopass" "stex")))) - ;; NOTE: the custom Chez 'configure' script doesn't allow - ;; unrecognized flags, such as those automatically added - ;; by `gnu-build-system`. - (replace 'configure - (lambda* (#:key inputs outputs - (configure-flags '()) - #:allow-other-keys) - (let* ((zlib-static (assoc-ref inputs "zlib:static")) - (lz4-static (assoc-ref inputs "lz4:static")) - (out (assoc-ref outputs "out")) - ;; add flags which are always required: - (flags (cons* (string-append "--installprefix=" out) + #:test-target "test" + ;; TODO when we fix armhf, it may not support --threads + #:configure-flags #~'("--threads") + #:phases + #~(modify-phases %standard-phases + (add-after 'unpack 'unpack-nanopass+stex + (lambda args + (copy-recursively #$nanopass + "nanopass" + #:keep-mtime? #t) + (copy-recursively #$stex + "stex" + #:keep-mtime? #t))) + ;; NOTE: the custom Chez 'configure' script doesn't allow + ;; unrecognized flags, such as those automatically added + ;; by `gnu-build-system`. + (replace 'configure + (lambda* (#:key inputs (configure-flags '()) #:allow-other-keys) + ;; add flags which are always required: + (let ((flags (cons* (string-append "--installprefix=" #$output) "ZLIB=-lz" "LZ4=-llz4" "--libkernel" @@ -272,90 +266,78 @@ (define src ;; and letting Chez try causes an error "--nogzip-man-pages" configure-flags))) - (format #t "configure flags: ~s~%" flags) - ;; Some makefiles (for tests) don't seem to propagate CC - ;; properly, so we take it out of their hands: - (setenv "CC" ,(cc-for-target)) - (setenv "HOME" "/tmp") - (apply invoke - "./configure" - flags)))) - ;; The binary file name is called "scheme" as is the one from MIT/GNU - ;; Scheme. We add a symlink to use in case both are installed. - (add-after 'install 'install-symlink - (lambda* (#:key outputs #:allow-other-keys) - (let* ((out (assoc-ref outputs "out")) - (bin (string-append out "/bin")) - (lib (string-append out "/lib")) - (name "chez-scheme")) - (symlink (string-append bin "/scheme") - (string-append bin "/" name)) - (map (lambda (file) - (symlink file (string-append (dirname file) - "/" name ".boot"))) - (find-files lib "scheme.boot"))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (stex-output "/tmp") - (doc-dir (string-append stex-output - "/share/doc/" - stex+version))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/" - stex+version) - (string-append "Scheme=" - (assoc-ref outputs "out") - "/bin/scheme")) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) - ;; Building the documentation requires stex and a running scheme. - ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - (let* ((chez+version (strip-store-file-name - (assoc-ref outputs "out"))) - (stex+version - (strip-store-file-name - (assoc-ref (or native-inputs inputs) "stex"))) - (scheme (string-append (assoc-ref outputs "out") - "/bin/scheme")) - ;; see note on stex-output in phase build-stex, above: - (stexlib (string-append "/tmp" - "/lib/" - stex+version)) - (doc-dir (string-append (assoc-ref outputs "doc") - "/share/doc/" - chez+version))) - (define* (stex-make #:optional (suffix "")) - (invoke "make" - "install" - (string-append "Scheme=" scheme) - (string-append "STEXLIB=" stexlib) - (string-append "installdir=" doc-dir suffix))) - (with-directory-excursion "csug" - (stex-make "/csug")) - (with-directory-excursion "release_notes" - (stex-make "/release_notes")) - (with-directory-excursion doc-dir - (symlink "release_notes/release_notes.pdf" - "release_notes.pdf") - (symlink "csug/csug9_5.pdf" - "csug.pdf")))))))) + (format #t "configure flags: ~s~%" flags) + ;; Some makefiles (for tests) don't seem to propagate CC + ;; properly, so we take it out of their hands: + (setenv "CC" #$(cc-for-target)) + (setenv "HOME" "/tmp") + (apply invoke "./configure" flags)))) + ;; The binary file name is called "scheme" as is the one from + ;; MIT/GNU Scheme. We add a symlink to use in case both are + ;; installed. + (add-after 'install 'install-symlink + (lambda* (#:key outputs #:allow-other-keys) + (let* ((scheme (search-input-file outputs "/bin/scheme")) + (bin-dir (dirname scheme))) + (symlink scheme + (string-append bin-dir "/chez-scheme")) + (match (find-files (string-append bin-dir "/../lib") + "scheme.boot") + ((scheme.boot) + (symlink scheme.boot + (string-append (dirname scheme.boot) + "/chez-scheme.boot"))))))) + ;; Building explicitly lets us avoid using substitute* + ;; to re-write makefiles. + (add-after 'install-symlink 'prepare-stex + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + ;; Eventually we want to install stex as a real + ;; package so it's reusable. For now: + (let* ((stex-output "/tmp") + (doc-dir (string-append stex-output "/share/doc/stex"))) + (with-directory-excursion "stex" + (invoke "make" + "install" + (string-append "LIB=" + stex-output + "/lib/stex") + (string-append "Scheme=" + (search-input-file outputs + "/bin/scheme"))) + (for-each (lambda (pth) + (install-file pth doc-dir)) + '("ReadMe" ; includes the license + "doc/stex.html" + "doc/stex.css" + "doc/stex.pdf")))))) + ;; Building the documentation requires stex and a running scheme. + ;; FIXME: this is probably wrong for cross-compilation + (add-after 'prepare-stex 'install-doc + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (match (assoc-ref outputs "doc") + (#f + (format #t "not installing docs~%")) + (doc-prefix + (let* ((chez+version (strip-store-file-name #$output)) + (scheme (search-input-file outputs "/bin/scheme")) + (stexlib "/tmp/lib/stex") + (doc-dir (string-append doc-prefix + "/share/doc/" + chez+version))) + (define* (stex-make #:optional (suffix "")) + (invoke "make" "install" + (string-append "Scheme=" scheme) + (string-append "STEXLIB=" stexlib) + (string-append "installdir=" doc-dir suffix))) + (with-directory-excursion "csug" + (stex-make "/csug")) + (with-directory-excursion "release_notes" + (stex-make "/release_notes")) + (with-directory-excursion doc-dir + (symlink "release_notes/release_notes.pdf" + "release_notes.pdf") + (symlink "csug/csug9_5.pdf" + "csug.pdf")))))))))) ;; Chez Scheme does not have a MIPS backend. ;; FIXME: Debian backports patches to get armhf working. ;; We should too. It is the Chez machine type arm32le diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 272638ca2e..035d93bfb5 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -257,10 +257,7 @@ (define (make-unpack-nanopass+stex) ;; TODO: Refactor enough to share this directly. #~(begin (copy-recursively - #$(match (assoc-ref (package-native-inputs chez-scheme) - "nanopass") - ((src) - src)) + #$nanopass "nanopass" #:keep-mtime? #t) (mkdir-p "stex") -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 18/24] gnu: Add stex. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (16 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 17/24] gnu: chez-scheme: Use new package style Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 19/24] gnu: Add chez-nanopass Philip McGrath ` (6 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (stex-bootstrap): New hidden package. (stex): Change from origin to package inheriting from 'stex-bootstrap' (chez-scheme)[native-inputs]: Add 'stex-bootstrap'. Remove dependencies of stex-bootstrap. [arguments]<#:phases>: Remove 'prepare-stex'. Adjust 'unpack-nanopass+stex' and 'install-doc'. --- gnu/packages/chez.scm | 217 ++++++++++++++++++++++++++++++------------ 1 file changed, 155 insertions(+), 62 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index ad263a8fe3..6855195cfe 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -33,6 +33,7 @@ (define-module (gnu packages chez) #:use-module (guix gexp) #:use-module (guix build-system copy) #:use-module (guix build-system gnu) + #:use-module (guix build-system copy) #:use-module (gnu packages compression) #:use-module (gnu packages ncurses) #:use-module (gnu packages ghostscript) @@ -158,30 +159,6 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) - -(define stex - ;; This commit includes a fix, which we would otherwise want to use as - ;; patch. Let's revert to tagged releases as soon as one becomes available. - (let* ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") - (version "1.2.2") - (version (git-version version "1" commit))) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/dybvig/stex") - (commit commit))) - (sha256 (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) - (file-name (git-file-name "stex" version))))) - (define-public chez-scheme (package (name "chez-scheme") @@ -218,15 +195,7 @@ (define-public chez-scheme libx11)) (native-inputs (list nanopass ; source only - ;; for docs - stex - xorg-rgb - (texlive-updmap.cfg (list texlive-dvips-l3backend - texlive-epsf - texlive-fonts-ec - texlive-oberdiek)) - ghostscript - netpbm)) + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -249,9 +218,11 @@ (define-public chez-scheme (copy-recursively #$nanopass "nanopass" #:keep-mtime? #t) - (copy-recursively #$stex - "stex" - #:keep-mtime? #t))) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -287,32 +258,9 @@ (define-public chez-scheme (symlink scheme.boot (string-append (dirname scheme.boot) "/chez-scheme.boot"))))))) - ;; Building explicitly lets us avoid using substitute* - ;; to re-write makefiles. - (add-after 'install-symlink 'prepare-stex - (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) - ;; Eventually we want to install stex as a real - ;; package so it's reusable. For now: - (let* ((stex-output "/tmp") - (doc-dir (string-append stex-output "/share/doc/stex"))) - (with-directory-excursion "stex" - (invoke "make" - "install" - (string-append "LIB=" - stex-output - "/lib/stex") - (string-append "Scheme=" - (search-input-file outputs - "/bin/scheme"))) - (for-each (lambda (pth) - (install-file pth doc-dir)) - '("ReadMe" ; includes the license - "doc/stex.html" - "doc/stex.css" - "doc/stex.pdf")))))) ;; Building the documentation requires stex and a running scheme. ;; FIXME: this is probably wrong for cross-compilation - (add-after 'prepare-stex 'install-doc + (add-after 'install-symlink 'install-doc (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) (match (assoc-ref outputs "doc") (#f @@ -320,7 +268,9 @@ (define-public chez-scheme (doc-prefix (let* ((chez+version (strip-store-file-name #$output)) (scheme (search-input-file outputs "/bin/scheme")) - (stexlib "/tmp/lib/stex") + (stexlib (search-input-directory (or native-inputs + inputs) + "/lib/stex")) (doc-dir (string-append doc-prefix "/share/doc/" chez+version))) @@ -420,7 +370,150 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (license (list asl2.0)))) ;; -;; Packages: +;; Chez's bootstrap dependencies: +;; + +(define-public stex-bootstrap + ;; This commit includes a fix which we would otherwise want to use as + ;; patch. Let's revert to tagged releases as soon as one becomes available. + (let ((commit "54051494434a197772bf6ca5b4e6cf6be55f39a5") + (revision "1")) + (hidden-package + (package + (name "stex") + ;; ^ Debian calls this "stex", not "chez-stex". It is a set of + ;; command-line tools, and there isn't a Scheme API, let alone a + ;; Chez-specific one, except perhaps that the Scheme examples are + ;; assumed to be Chez-compatible. + (version (git-version "1.2.2" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/dybvig/stex") + (commit commit))) + (sha256 + (base32 "01jnvw8qw33gnpzwrakwhsr05h6b609lm180jnspcrb7lds2p23d")) + (file-name (git-file-name name version)) + (snippet + #~(for-each delete-file + '("sbin/install" "doc/stex.pdf" "doc/stex.html"))))) + (outputs '("out")) + (build-system copy-build-system) + ;; N.B. Upstream does not seem to support cross-compilation, + ;; though it would probably be easy to add. + (propagated-inputs + (list xorg-rgb + (texlive-updmap.cfg + (list texlive-dvips-l3backend + texlive-hyperref + texlive-bibtex + texlive-epsf + texlive-fonts-ec + texlive-oberdiek)) + ghostscript + netpbm)) + ;; Debian uses a versionless path for STEXLIB, + ;; which is much more convienient. + (arguments + (list + #:install-plan #~`(("inputs" "lib/stex/") + ("gifs" "lib/stex/") + ("math" "lib/stex/") + ("src" "lib/stex/") + ("Mf-stex" "lib/stex/") + ("Makefile.template" "lib/stex/")) + #:phases + #~(modify-phases %standard-phases + (add-before 'install 'patch-sources + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (define scheme + (false-if-exception + (search-input-file inputs "/bin/scheme"))) + (when scheme + (setenv "Scheme" scheme)) + (substitute* '("Makefile.template" + "doc/Makefile") + (("STEXLIB=[^\n]*") + (string-append "STEXLIB=" #$output "/lib/stex")) + (("Scheme=[^\n]*") + (string-append "Scheme=" (or scheme "scheme")))) + (substitute* '("Mf-stex" + "math/Makefile") + (("/bin/rm") + "rm")) + (substitute* "Mf-stex" + (("SHELL=bash") + ;; avoid Solaris workaround + "#SHELL=bash")))) + (add-after 'install 'maybe-compile + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((getenv "Scheme") + => (lambda (scheme) + (define makefile + (string-append (getcwd) "/Makefile")) + (define machine + #$(chez-machine->threaded + (nix-system->chez-machine))) + (with-directory-excursion + (search-input-directory outputs "/lib/stex") + (invoke "make" + "-f" makefile + (string-append "Scheme=" scheme)) + (for-each delete-file + (find-files machine "\\."))))) + (else + ;; for bootstrapping, can run without ahead-of-time + ;; compilation + (format #t "not compiling~%"))))) + (add-after 'maybe-compile 'maybe-make-docs + (lambda* (#:key native-inputs inputs outputs #:allow-other-keys) + (cond + ((assoc-ref outputs "doc") + => (lambda (doc-prefix) + (define doc-dir + (string-append doc-prefix "/share/doc/stex")) + ;; the Makefile is referenced in the documentation + (copy-recursively "doc" doc-dir) + (install-file "ReadMe" doc-dir) + (with-directory-excursion "doc" + (invoke "make") + (install-file "stex.html" doc-dir) + (install-file "stex.pdf" doc-dir)))) + (else + (format #t "not making docs~%")))))))) + (home-page "https://github.com/dybvig/stex") + (synopsis "LaTeX with embeded Scheme code and HTML generation") + (description "The @code{stex} package extends LaTeX with a handful of +commands for including Scheme code (or pretty much any other kind of code, as +long as you don't plan to use the Scheme-specific transcript support) in a +document. It provides the programs @code{scheme-prep} and @code{html-prep} to +convert @code{stex} documents to LaTeX and HTML, respectively, plus makefile +templates, style files, and other resources. The @code{stex} system is used +to typeset @cite{The Scheme Programming Language} and the @cite{Chez Scheme +User's Guix}, among other documents.") + (license expat))))) + +(define-public stex + (package/inherit stex-bootstrap + (inputs (modify-inputs (package-inputs stex-bootstrap) + (prepend chez-scheme))) + (outputs '("out" "doc")) + (properties '()))) + +(define-public nanopass + (let ((version "1.9.2")) + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass" version))))) + +;; +;; Other Chez packages: ;; ;; Help function for Chez Scheme to add the current path to -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 19/24] gnu: Add chez-nanopass. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (17 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 18/24] gnu: Add stex Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath ` (5 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (nanopass): Rename to ... (chez-nanopass-bootstrap): ... this new variable, and promote it from an origin to a package. (chez-nanopass): New variable. (unpack-nanopass+stex): New variable using 'chez-nanopass-bootstrap'. (chez-scheme-for-racket-bootstrap-bootfiles, chez-scheme)[native-inputs]: Add 'chez-nanopass-bootstrap'. [arguments]<#:phases>: Adapt 'unpack-nanopass+stex' phase to use the eponymous new variable. * gnu/packages/racket.scm (racket-vm-cs): Likewise. (make-unpack-nanopass+stex): Remove it. --- gnu/packages/chez.scm | 122 +++++++++++++++++++++++++++++++--------- gnu/packages/racket.scm | 19 +------ 2 files changed, 98 insertions(+), 43 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 6855195cfe..43d2c764f3 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -48,7 +48,8 @@ (define-module (gnu packages chez) #:use-module (srfi srfi-1) #:export (nix-system->chez-machine chez-machine->nonthreaded - chez-machine->threaded)) + chez-machine->threaded + unpack-nanopass+stex)) (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string @@ -159,6 +160,20 @@ (define* (chez-upstream-features-for-system #:optional ;; Chez Scheme: ;; + +(define unpack-nanopass+stex + #~(begin + (copy-recursively + (dirname (search-input-file %build-inputs + "lib/chez-scheme/nanopass.ss")) + "nanopass" + #:keep-mtime? #t) + (mkdir-p "stex") + (with-output-to-file "stex/Mf-stex" + (lambda () + ;; otherwise, it will try to download submodules + (display "# to placate ../configure"))))) + (define-public chez-scheme (package (name "chez-scheme") @@ -176,6 +191,9 @@ (define-public chez-scheme (file-name (git-file-name name version)) (snippet #~(begin (use-modules (guix build utils)) + ;; TODO: consider putting this in a (guix ...) or + ;; (guix build ...) module so it can be shared + ;; with the Racket origin without cyclic issues. (for-each (lambda (dir) (when (directory-exists? dir) (delete-file-recursively dir))) @@ -193,9 +211,7 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs - (list nanopass ; source only - stex-bootstrap)) + (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -215,14 +231,7 @@ (define-public chez-scheme #~(modify-phases %standard-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args - (copy-recursively #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) + #$unpack-nanopass+stex)) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -317,7 +326,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm (inputs `()) - (native-inputs (list racket-vm-bc)) + (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -336,10 +345,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (chdir "racket/src/ChezScheme"))) (add-after 'chdir 'unpack-nanopass+stex (lambda args - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t))) + #$unpack-nanopass+stex)) (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) @@ -502,15 +508,79 @@ (define-public stex (outputs '("out" "doc")) (properties '()))) -(define-public nanopass - (let ((version "1.9.2")) - (origin - (method git-fetch) - (uri (git-reference - (url "https://github.com/nanopass/nanopass-framework-scheme") - (commit (string-append "v" version)))) - (sha256 (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) - (file-name (git-file-name "nanopass" version))))) +(define-public chez-nanopass-bootstrap + (hidden-package + (package + (name "chez-nanopass") + (version "1.9.2") + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/nanopass/nanopass-framework-scheme") + (commit (string-append "v" version)))) + (sha256 + (base32 "16vjsik9rrzbabbhbxbaha51ppi3f9n8rk59pc6zdyffs0vziy4i")) + (file-name (git-file-name "nanopass-framework-scheme" version)) + (snippet + #~(begin + (use-modules (guix build utils)) + (when (file-exists? "doc/user-guide.pdf") + (delete-file "doc/user-guide.pdf")) + (substitute* "doc/Makefile" + (("include ~/stex/Mf-stex") + "include $(STEXLIB)/Mf-stex")))))) + (build-system copy-build-system) + (arguments + (list #:install-plan + #~`(("nanopass.ss" "lib/chez-scheme/") + ("nanopass" "lib/chez-scheme/")))) + (home-page "https://nanopass.org") + (synopsis "DSL for compiler development") + (description "The Nanopass framework is an embedded domain-specific +language for writing compilers composed of several simple passes that +operate over well-defined intermediate languages. The goal of this +organization is both to simplify the understanding of each pass, because it +is responsible for a single task, and to simplify the addition of new passes +anywhere in the compiler. Nanopass reduces the boilerplate required to +create compilers, making them easier to understand and maintain.") + (license expat)))) + +(define-public chez-nanopass + (package/inherit chez-nanopass-bootstrap + (properties '()) + ;; TODO: cross-compilation + (native-inputs (list chez-scheme stex)) + (arguments + (substitute-keyword-arguments (package-arguments chez-nanopass-bootstrap) + ((#:install-plan base-plan) + #~`(("nanopass.so" "lib/chez-scheme/") + ("doc/user-guide.pdf" #$(string-append + "share/doc/" + (package-name this-package) + "-" + (package-version this-package) + "/")) + ,@#$base-plan)) + ((#:phases base-phases #~%standard-phases) + #~(modify-phases #$base-phases + (add-before 'install 'compile-and-test + (lambda args + (invoke "scheme" + "--compile-imported-libraries" + "--program" "test-all.ss"))) + (add-after 'compile-and-test 'build-doc + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (with-directory-excursion "doc" + (invoke "make" + (string-append "Scheme=" + (search-input-file + (or native-inputs inputs) + "/bin/scheme")) + (string-append "STEXLIB=" + (search-input-directory + (or native-inputs inputs) + "/lib/stex")))))))))))) ;; ;; Other Chez packages: diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 035d93bfb5..f29e0791a7 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -251,22 +251,6 @@ (define (racket-vm-common-configure-flags) "--disable-strip" "--enable-origtree")) -(define (make-unpack-nanopass+stex) - ;; Adapted from chez-scheme. - ;; Thunked to avoid evaluating 'chez-scheme' too early. - ;; TODO: Refactor enough to share this directly. - #~(begin - (copy-recursively - #$nanopass - "nanopass" - #:keep-mtime? #t) - (mkdir-p "stex") - (with-output-to-file "stex/Mf-stex" - (lambda () - ;; otherwise, it will try to download submodules - (display "# to placate ../configure"))))) - - (define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. @@ -417,6 +401,7 @@ (define-public racket-vm-cs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles + chez-nanopass-bootstrap racket-vm-bc))) (arguments (substitute-keyword-arguments (package-arguments racket-vm-cgc) @@ -425,7 +410,7 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$(make-unpack-nanopass+stex)))) + #$unpack-nanopass+stex))) (add-after 'unpack-nanopass+stex 'unpack-bootfiles (lambda* (#:key native-inputs inputs #:allow-other-keys) (with-directory-excursion "racket/src/ChezScheme" -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (18 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 19/24] gnu: Add chez-nanopass Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath ` (4 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes This makes the structure of the upstream Chez Scheme package the same as for the Racket variant, it sets things up for (one day, hopefully) actually being able to bootstrap the upstream Chez Scheme bootfiles, and it may be useful for cross-compilation and adding support for architectures without pre-built bootfiles from upstream. * gnu/packages/chez.scm (chez-scheme-bootstrap-bootfiles): New variable. (chez-scheme)[native-inputs]: Add it. [arguments]<#:phases>: Add 'unpack-bootfiles'. (chez-scheme-for-racket-bootstrap-bootfiles): Inherit from 'chez-scheme-bootstrap-bootfiles'. [arguments]: Adapt accordingly. --- gnu/packages/chez.scm | 98 +++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 43d2c764f3..da267d3616 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -46,6 +46,7 @@ (define-module (gnu packages chez) #:use-module (gnu packages xorg) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded @@ -211,7 +212,9 @@ (define-public chez-scheme ;; for X11 clipboard support in expeditor: ;; https://github.com/cisco/ChezScheme/issues/9#issuecomment-222057232 libx11)) - (native-inputs (list chez-nanopass-bootstrap stex-bootstrap)) + (native-inputs (list chez-scheme-bootstrap-bootfiles + chez-nanopass-bootstrap + stex-bootstrap)) (native-search-paths (list (search-path-specification (variable "CHEZSCHEMELIBDIRS") @@ -232,6 +235,14 @@ (define-public chez-scheme (add-after 'unpack 'unpack-nanopass+stex (lambda args #$unpack-nanopass+stex)) + (add-after 'unpack-nanopass+stex 'unpack-bootfiles + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (when (directory-exists? "boot") + (delete-file-recursively "boot")) + (copy-recursively + (search-input-directory (or native-inputs inputs) + "lib/chez-scheme-bootfiles") + "boot"))) ;; NOTE: the custom Chez 'configure' script doesn't allow ;; unrecognized flags, such as those automatically added ;; by `gnu-build-system`. @@ -316,8 +327,46 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-bootstrap-bootfiles + (package + (inherit chez-scheme) + (name "chez-scheme-bootstrap-bootfiles") + (inputs '()) + (native-inputs '()) + (outputs '("out")) + (build-system copy-build-system) + ;; TODO: cross compilation + (arguments + (list #:install-plan + #~`(("boot/" "lib/chez-scheme-bootfiles")))) + (supported-systems + ;; Upstream only distributes pre-built bootfiles for + ;; arm32le and t?(i3|a6)(le|nt|osx) + (filter (lambda (system) + (let ((machine (and=> (nix-system->chez-machine system) + chez-machine->nonthreaded))) + (or (equal? "arm32le" machine) + (and machine + (member (substring machine 0 2) '("i3" "a6")) + (or-map (cut string-suffix? <> machine) + '("le" "nt" "osx")))))) + %supported-systems)) + (synopsis "Chez Scheme bootfiles (binary seed)") + (description + "Chez Scheme is a self-hosting compiler: building it requires +``bootfiles'' containing the Scheme-implemented portions compiled for the +current platform. (Chez can then cross-compile bootfiles for all other +supported platforms.) + +This package provides bootstrap bootfiles for upstream Chez Scheme. +Currently, it simply packages the binaries checked in to the upsream +repository. Hopefully we can eventually adapt Racket's @code{cs-bootstrap} to +work with upstream Chez Scheme so that we can bootstrap these files from +source."))) + (define-public chez-scheme-for-racket-bootstrap-bootfiles (package + (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") (version "9.5.7.3") ;; The version should match `(scheme-fork-version-number)`. @@ -325,32 +374,30 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; It will always be different than the upstream version! ;; When updating, remember to also update %racket-version in racket.scm. (source #f) ; avoid problematic cycle with racket.scm - (inputs `()) (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) - (build-system copy-build-system) ;; TODO: cross compilation (arguments - (list - #:install-plan - #~`(("boot/" "lib/chez-scheme-bootfiles")) - #:phases - #~(let ((unpack (assoc-ref %standard-phases 'unpack))) - (modify-phases %standard-phases - (replace 'unpack - (lambda args - (unpack #:source #$(or (package-source this-package) - (package-source racket-vm-bc))))) - (add-after 'unpack 'chdir - (lambda args - (chdir "racket/src/ChezScheme"))) - (add-after 'chdir 'unpack-nanopass+stex - (lambda args - #$unpack-nanopass+stex)) - (add-before 'install 'build - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (invoke (search-input-file (or native-inputs inputs) - "/opt/racket-vm/bin/racket") - "rktboot/main.rkt"))))))) + (substitute-keyword-arguments + (package-arguments chez-scheme-bootstrap-bootfiles) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme"))) + (add-after 'chdir 'unpack-nanopass+stex + (lambda args + #$unpack-nanopass+stex)) + (add-before 'install 'build + (lambda* (#:key native-inputs inputs #:allow-other-keys) + (invoke (search-input-file (or native-inputs inputs) + "/opt/racket-vm/bin/racket") + "rktboot/main.rkt")))))))) (supported-systems (filter nix-system->chez-machine %supported-systems)) (home-page "https://github.com/racket/ChezScheme") @@ -372,8 +419,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles Note that the generated bootfiles are specific to Racket's fork of Chez Scheme, and @code{cs-bootstrap} does not currently support building upstream -Chez Scheme.") - (license (list asl2.0)))) +Chez Scheme."))) ;; ;; Chez's bootstrap dependencies: -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 21/24] gnu: chez-mit: Support chez-scheme-for-racket. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (19 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 22/24] gnu: Add chez-scheme-for-racket Philip McGrath ` (3 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Racket's variant of Chez Scheme defines 'string->uninterned-symbol', which conflicts with the definition from '(chez mit)'. See discussion at <https://github.com/racket/racket/issues/4151>. * gnu/packages/chez.scm (chez-mit)[origin]<snippet>: Add workaround for chez-scheme-for-racket. --- gnu/packages/chez.scm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index da267d3616..5d5108a2b1 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -949,7 +949,29 @@ (define-public chez-mit (commit (string-append "v" version)))) (sha256 (base32 "0c7i3b6i90xk96nmxn1pc9272a4yal4v40dm1a4ybdi87x53zkk0")) - (file-name (git-file-name name version)))) + (file-name (git-file-name name version)) + (snippet + ;; Workaround for chez-scheme-for-racket. + ;; See: https://github.com/racket/racket/issues/4151 + #~(begin + (use-modules (guix build utils)) + (substitute* "mit/core.sls" + (("[(]import ") + "(import (only (chezscheme) import)\n") + (("[(]define string->uninterned-symbol gensym[)]") + (format #f "~s" + '(begin + (import (only (chezscheme) + meta-cond + library-exports)) + (meta-cond + ((memq 'string->uninterned-symbol + (library-exports '(chezscheme))) + (import (only (chezscheme) + string->uninterned-symbol))) + (else + (define string->uninterned-symbol + gensym))))))))))) (build-system gnu-build-system) (inputs (list chez-srfi)) ; for tests -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 22/24] gnu: Add chez-scheme-for-racket. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (20 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath ` (2 subsequent siblings) 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes The Racket variant of Chez Scheme can be used to support platforms that are not yet supported by upstream Chez Scheme. * gnu/packages/chez.scm (chez-scheme-for-racket): New variable. (chez-scheme-for-racket-bootstrap-bootfiles)[version, supported-systems]: Derive from 'chez-scheme-for-racket'. * gnu/packages/racket.scm (%racket-version): Update comment. --- gnu/packages/chez.scm | 97 ++++++++++++++++++++++++++++++++++++++--- gnu/packages/racket.scm | 3 +- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index 5d5108a2b1..e7ddab0d1f 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -52,6 +52,21 @@ (define-module (gnu packages chez) chez-machine->threaded unpack-nanopass+stex)) +;; Commentary: +;; +;; The bootstrapping paths for Chez Scheme and Racket are closely +;; entwined. Racket CS (the default Racket implementation) is based on (a fork +;; of) Chez Scheme. Racket's variant of Chez Scheme shares sources for +;; nanopass and stex with upstream Chez Scheme. +;; +;; Racket's variant of Chez Scheme can be bootstrapped by an older Racket +;; implementation, Racket BC, which can be bootstrapped from C. Porting that +;; code to work with upstream Chez Scheme (or finding an old version that +;; does) is our best hope for some day bootstrapping upstream Chez Scheme from +;; source. +;; +;; Code: + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -327,6 +342,78 @@ (define* (stex-make #:optional (suffix "")) and 32-bit PowerPC architectures.") (license asl2.0))) +(define-public chez-scheme-for-racket + (package + (inherit chez-scheme) + (name "chez-scheme-for-racket") + (version "9.5.7.3") + ;; The version should match `(scheme-fork-version-number)`. + ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. + ;; It will always be different than the upstream version! + ;; When updating, remember to also update %racket-version in racket.scm. + (source #f) ; avoid problematic cycle with racket.scm + (inputs + (modify-inputs (package-inputs chez-scheme) + (delete "libx11" "util-linux:lib"))) + (native-inputs + (modify-inputs (package-native-inputs chez-scheme) + (replace "chez-scheme-bootstrap-bootfiles" + chez-scheme-for-racket-bootstrap-bootfiles))) + (arguments + (substitute-keyword-arguments (package-arguments chez-scheme) + ((#:configure-flags cfg-flags #~'()) + #~(cons "--disable-x11" #$cfg-flags)) + ((#:phases those-phases #~%standard-phases) + #~(let* ((those-phases #$those-phases) + (unpack (assoc-ref those-phases 'unpack))) + (modify-phases those-phases + (replace 'unpack + (lambda args + (unpack #:source #$(or (package-source this-package) + (package-source racket-vm-bc))))) + (add-after 'unpack 'chdir + (lambda args + (chdir "racket/src/ChezScheme")))))))) + (supported-systems (filter nix-system->chez-machine + %supported-systems)) + (home-page "https://github.com/racket/ChezScheme") + ;; ^ This is downstream of https://github.com/racket/racket, + ;; but it's designed to be a friendly landing place for people + ;; who want a ChezScheme-shaped repositroy. + (synopsis "Variant of Chez Scheme extended for Racket") + (description "This variant of Chez Scheme is extended to support the +implementation of Racket. It may be useful on platforms that are not yet +supported by upstream Chez Scheme. + +Main additions to Chez Scheme in the Racket variant: +@itemize @bullet +@item +AArch64 support +@item +Portable bytes (@code{pb}) support, which is mainly useful for bootstrapping +a build on any supported platform +@item +Unboxed floating-point arithmetic and flvectors +@item +Type reconstruction during optimization (especially for safe code) +@item +Continuation attachments +@item +Parallel garbage collection, in-place garbage collection for old-generation +objects (instead of always copying), and reachability-based memory +accounting +@item +Ordered finalization, immobile (but collectable) objects, weak/ephemeron +generic hash tables, and reference bytevectors +@item +Faster multiplication and division for large exact numbers +@end itemize") + (license asl2.0))) + +;; +;; Bootfiles: +;; + (define-public chez-scheme-bootstrap-bootfiles (package (inherit chez-scheme) @@ -368,11 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (package (inherit chez-scheme-bootstrap-bootfiles) (name "chez-scheme-for-racket-bootstrap-bootfiles") - (version "9.5.7.3") - ;; The version should match `(scheme-fork-version-number)`. - ;; See racket/src/ChezScheme/s/cmacros.ss c. line 360. - ;; It will always be different than the upstream version! - ;; When updating, remember to also update %racket-version in racket.scm. + (version (package-version chez-scheme-for-racket)) (source #f) ; avoid problematic cycle with racket.scm (native-inputs (list chez-nanopass-bootstrap racket-vm-bc)) ;; TODO: cross compilation @@ -398,8 +481,8 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (invoke (search-input-file (or native-inputs inputs) "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))))) - (supported-systems (filter nix-system->chez-machine - %supported-systems)) + (supported-systems + (package-supported-systems chez-scheme-for-racket)) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, ;; but it's designed to be a friendly landing place for people diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index f29e0791a7..50ef8c1f5e 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -195,8 +195,7 @@ (define* (racket-vm-for-system #:optional racket-vm-cs racket-vm-bc)) -(define %racket-version "8.4") -;; ^ Remember to update chez-scheme-for-racket-bootstrap-bootfiles! +(define %racket-version "8.4") ; Remember to update chez-scheme-for-racket! (define %racket-commit (string-append "v" %racket-version)) (define %racket-origin -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 23/24] gnu: chez: Add 'chez-scheme-for-system'. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (21 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 22/24] gnu: Add chez-scheme-for-racket Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 2022-03-04 22:59 ` bug#53878: [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/chez.scm (chez-scheme-for-system): New procedure. (chez-srfi, chez-web, chez-sockets, chez-matchable, chez-irregex, chez-fmt, chez-mit, chez-scmutils): Use 'chez-scheme-for-system'. * gnu/packages/loko.scm (loko-scheme): Likewise. * gnu/packages/emacs-xyz.scm (emacs-geiser-chez): Likewise --- gnu/packages/chez.scm | 33 ++++++++++++++++++++++++--------- gnu/packages/emacs-xyz.scm | 2 +- gnu/packages/loko.scm | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/gnu/packages/chez.scm b/gnu/packages/chez.scm index e7ddab0d1f..b3aadf3a78 100644 --- a/gnu/packages/chez.scm +++ b/gnu/packages/chez.scm @@ -47,7 +47,8 @@ (define-module (gnu packages chez) #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) - #:export (nix-system->chez-machine + #:export (chez-scheme-for-system + nix-system->chez-machine chez-machine->nonthreaded chez-machine->threaded unpack-nanopass+stex)) @@ -67,6 +68,20 @@ (define-module (gnu packages chez) ;; ;; Code: +(define* (chez-scheme-for-system #:optional + (system (or (%current-target-system) + (%current-system)))) + "Return 'chez-scheme' unless only 'chez-scheme-for-racket' supports SYSTEM, +including support for native threads." + (if (or + ;; full support upstream + (and=> (chez-upstream-features-for-system system) + (cut memq 'threads <>)) + ;; no support anywhere + (not (nix-system->chez-machine system))) + chez-scheme + chez-scheme-for-racket)) + (define (chez-machine->nonthreaded machine) "Given a string MACHINE naming a Chez Scheme machine type, returns a string naming the nonthreaded machine type for the same architecture and OS as @@ -751,7 +766,7 @@ (define-public chez-srfi (file-name (git-file-name name version)))) (build-system gnu-build-system) (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -782,7 +797,7 @@ (define-public chez-web (base32 "1dq25qygyncbfq4kwwqqgyyakfqjwhp5q23vrf3bff1p66nyfl3b")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) ghostscript ;; FIXME: This package fails to build with the error: ;; mktexpk: don't know how to create bitmap font for bchr8r @@ -847,7 +862,7 @@ (define-public chez-sockets (base32 "1n5fbwwz51fdzvjackgmnsgh363g9inyxv7kmzi0469cwavwcx5m")))) (build-system gnu-build-system) (native-inputs - (list chez-scheme + (list (chez-scheme-for-system) chez-web (texlive-updmap.cfg (list texlive-pdftex)))) (arguments @@ -933,7 +948,7 @@ (define-public chez-matchable (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -965,7 +980,7 @@ (define-public chez-irregex (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -996,7 +1011,7 @@ (define-public chez-fmt (propagated-inputs (list chez-srfi)) ; for irregex-utils (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "chez-check" @@ -1059,7 +1074,7 @@ (define string->uninterned-symbol (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (arguments (list #:make-flags (chez-make-flags name version) #:test-target "test" @@ -1090,7 +1105,7 @@ (define-public chez-scmutils (inputs (list chez-srfi)) ; for tests (native-inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list chez-mit chez-srfi)) (arguments diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm index ef98088100..df53df61c7 100644 --- a/gnu/packages/emacs-xyz.scm +++ b/gnu/packages/emacs-xyz.scm @@ -451,7 +451,7 @@ (define-public emacs-geiser-chez (string-append "(eval-after-load 'geiser-impl '" all ")")))))))) (inputs - (list chez-scheme)) + (list (chez-scheme-for-system))) (propagated-inputs (list emacs-geiser)) (home-page "https://nongnu.org/geiser/") diff --git a/gnu/packages/loko.scm b/gnu/packages/loko.scm index ef9312afe3..449c62f1f0 100644 --- a/gnu/packages/loko.scm +++ b/gnu/packages/loko.scm @@ -71,7 +71,7 @@ (define-public loko-scheme #t))))) (native-inputs `(("akku" ,akku) - ("chez-scheme" ,chez-scheme) + ("chez-scheme" ,(chez-scheme-for-system)) ("struct" ,guile-struct-pack) ("laesare" ,guile-laesare) ("pfds" ,guile-pfds) -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* [bug#53878] [PATCH v7 24/24] gnu: racket-vm-cs: Build with "--enable-scheme". 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (22 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath @ 2022-02-27 21:29 ` Philip McGrath 2022-03-04 22:59 ` bug#53878: [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler 24 siblings, 0 replies; 214+ messages in thread From: Philip McGrath @ 2022-02-27 21:29 UTC (permalink / raw) To: 53878, Liliana Marie Prikler, zimoun Cc: Philip McGrath, Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes * gnu/packages/racket.scm (racket-vm-cs)[native-inputs]: Remove 'chez-scheme-for-racket-bootstrap-bootfiles'. Add 'chez-scheme-for-racket'. [arguments]<#:phases>: Delete 'unpack-bootfiles'. <#:configure-flags>: Add "--enable-scheme". --- gnu/packages/racket.scm | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 50ef8c1f5e..8d44241414 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -399,7 +399,7 @@ (define-public racket-vm-cs (native-inputs (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") - (prepend chez-scheme-for-racket-bootstrap-bootfiles + (prepend chez-scheme-for-racket chez-nanopass-bootstrap racket-vm-bc))) (arguments @@ -409,18 +409,15 @@ (define-public racket-vm-cs (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" - #$unpack-nanopass+stex))) - (add-after 'unpack-nanopass+stex 'unpack-bootfiles - (lambda* (#:key native-inputs inputs #:allow-other-keys) - (with-directory-excursion "racket/src/ChezScheme" - (copy-recursively - (search-input-directory (or native-inputs inputs) - "lib/chez-scheme-bootfiles") - "boot")))))) + #$unpack-nanopass+stex))))) ((#:configure-flags _ '()) #~(cons* "--enable-csonly" "--enable-libz" "--enable-lz4" + (string-append "--enable-scheme=" + #$(this-package-native-input + "chez-scheme-for-racket") + "/bin/scheme") #$(racket-vm-common-configure-flags))))) (synopsis "Racket CS implementation") (description "The Racket CS implementation, which uses ``Chez Scheme'' as -- 2.32.0 ^ permalink raw reply related [flat|nested] 214+ messages in thread
* bug#53878: [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages. 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath ` (23 preceding siblings ...) 2022-02-27 21:29 ` [bug#53878] [PATCH v7 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath @ 2022-03-04 22:59 ` Liliana Marie Prikler 24 siblings, 0 replies; 214+ messages in thread From: Liliana Marie Prikler @ 2022-03-04 22:59 UTC (permalink / raw) To: Philip McGrath, 53878-done, zimoun Cc: Ludovic Courtès, Maxime Devos, raingloom, Liliana Marie Prikler, Attila Lendvai, Malte Gerdes Hi Philip, Am Sonntag, dem 27.02.2022 um 16:28 -0500 schrieb Philip McGrath: > Hi, > > On Sunday, February 27, 2022 3:42:46 AM EST Liliana Marie Prikler > wrote: > > > > Perhaps I wasn't clear enough about this in v5, but I think spec > > should > > be a single argument rather than multiple ones. This way, if we do > > find that we need to extend it to support an additional argument, > > we > > don't have to awkwardly code around the #:rest. > > > > Rather than debate it, I'm sending a v7 with the change to patch > 03/24 that Liliana requested in > <https://issues.guix.gnu.org/53878#187>. Sorry for the delay. I cleaned up some of your commits and their messages, but apart from that pushed v7 without major changes. I'm marking this as done now; if you feel I've made a mistake somewhere, don't hesitate to reopen. Cheers ^ permalink raw reply [flat|nested] 214+ messages in thread
end of thread, other threads:[~2022-06-13 7:36 UTC | newest] Thread overview: 214+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-02-08 15:13 [bug#53878] [RFC PATCH 0/9] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 1/9] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 2/9] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 3/9] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 4/9] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 5/9] gnu: Add stex Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 6/9] gnu: Add chez-nanopass Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 7/9] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 8/9] gnu: Add chez-scheme-racket-variant Philip McGrath 2022-02-09 13:42 ` Liliana Marie Prikler 2022-02-10 1:30 ` Philip McGrath 2022-02-10 7:08 ` Liliana Marie Prikler 2022-02-13 21:51 ` [bug#53878] [PATCH 00/11] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 01/11] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 02/11] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 03/11] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 04/11] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath 2022-02-14 14:34 ` Liliana Marie Prikler 2022-02-16 22:54 ` Philip McGrath 2022-02-17 7:24 ` Liliana Marie Prikler 2022-02-17 7:37 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 05/11] gnu: Add stex Philip McGrath 2022-02-14 14:46 ` Liliana Marie Prikler [not found] ` <72f7937e-7476-a48c-56af-8f68834d4359@philipmcgrath.com> 2022-02-16 20:46 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 06/11] gnu: Add chez-nanopass Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 07/11] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-14 14:54 ` Liliana Marie Prikler 2022-02-16 21:13 ` Philip McGrath 2022-02-17 7:10 ` Liliana Marie Prikler 2022-02-17 8:06 ` Philip McGrath 2022-02-17 8:19 ` Liliana Marie Prikler 2022-02-17 8:40 ` Philip McGrath 2022-02-17 8:46 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-18 6:57 ` Liliana Marie Prikler 2022-02-18 22:12 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath 2022-02-18 6:49 ` Liliana Marie Prikler 2022-02-18 22:32 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 05/15] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-18 7:15 ` Liliana Marie Prikler 2022-02-18 22:43 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 06/15] gnu: Add stex Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 07/15] gnu: Add chez-nanopass Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-18 7:08 ` Liliana Marie Prikler 2022-02-18 23:20 ` Philip McGrath 2022-02-19 14:46 ` Liliana Marie Prikler 2022-02-17 20:50 ` [bug#53878] [PATCH v2 09/15] gnu: Add racket-vm-cgc Philip McGrath 2022-02-18 7:21 ` Liliana Marie Prikler 2022-02-18 23:40 ` Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 10/15] gnu: Add racket-vm-bc Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 11/15] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 12/15] gnu: Add racket-vm-cs Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-17 20:50 ` [bug#53878] [PATCH v2 15/15] gnu: racket: Update to 8.4 Philip McGrath 2022-02-18 7:38 ` Liliana Marie Prikler 2022-02-19 2:07 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 08/11] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-14 15:18 ` Liliana Marie Prikler 2022-02-16 19:58 ` Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 09/11] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 10/11] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-13 21:51 ` [bug#53878] [PATCH 11/11] gnu: racket: Update to 8.4 Philip McGrath 2022-02-14 15:28 ` Liliana Marie Prikler 2022-02-16 20:16 ` Philip McGrath 2022-02-08 15:18 ` [bug#53878] [RFC PATCH 9/9] gnu: racket: Update to 8.3.900 Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 05/15] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 06/15] gnu: Add stex Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 07/15] gnu: Add chez-nanopass Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath 2022-02-19 20:46 ` Liliana Marie Prikler [not found] ` <2223439.vW7IG60toP@bastet> 2022-02-20 9:03 ` Liliana Marie Prikler 2022-02-20 14:09 ` Philip McGrath 2022-02-20 16:48 ` Liliana Marie Prikler 2022-02-20 17:52 ` Philip McGrath 2022-02-20 18:13 ` Liliana Marie Prikler 2022-02-23 18:55 ` Philip McGrath 2022-02-23 20:31 ` Liliana Marie Prikler 2022-02-24 15:09 ` zimoun 2022-02-19 6:42 ` [bug#53878] [PATCH v3 10/15] gnu: Add racket-vm-bc Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 11/15] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 12/15] gnu: Add racket-vm-cs Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-19 6:42 ` [bug#53878] [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-19 20:00 ` Liliana Marie Prikler 2022-02-19 6:42 ` [bug#53878] [PATCH v3 15/15] gnu: racket: Update to 8.4 Philip McGrath 2022-02-19 22:34 ` [bug#53878] Fwd: Re: [PATCH v3 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-19 22:35 ` [bug#53878] Fwd: Re: [PATCH v3 09/15] gnu: Add racket-vm-cgc Philip McGrath 2022-02-19 23:24 ` Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 00/15] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 01/15] gnu: chez-scheme: Move to (gnu packages chez-and-racket-bootstrap) Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 02/15] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 03/15] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-20 6:05 ` [bug#53878] [PATCH v4 04/15] gnu: chez-and-racket-bootstrap: Add utilities for Chez machine types Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 05/15] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 06/15] gnu: Add stex Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 07/15] gnu: Add chez-nanopass Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 08/15] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 09/15] gnu: Add racket-vm-cgc Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 10/15] gnu: Add racket-vm-bc Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 11/15] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 12/15] gnu: Add racket-vm-cs Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 13/15] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 14/15] gnu: chez-and-racket-bootstrap: Add 'chez-scheme-for-system' Philip McGrath 2022-02-20 6:06 ` [bug#53878] [PATCH v4 15/15] gnu: racket: Update to 8.4 Philip McGrath 2022-02-20 10:16 ` Liliana Marie Prikler 2022-02-20 14:09 ` Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 01/22] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 02/22] gnu: racket: Update to 8.4 Philip McGrath 2022-02-26 13:36 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 03/22] gnu: racket: Use Git origins for Racket packages Philip McGrath 2022-02-26 13:47 ` Liliana Marie Prikler 2022-02-26 14:20 ` Philip McGrath 2022-02-26 14:26 ` Liliana Marie Prikler 2022-02-26 17:23 ` Philip McGrath 2022-02-26 18:30 ` Liliana Marie Prikler 2022-02-26 19:55 ` Philip McGrath 2022-02-26 21:09 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 04/22] gnu: racket-minimal: Use new package style Philip McGrath 2022-02-26 14:14 ` Liliana Marie Prikler 2022-02-26 14:22 ` Philip McGrath 2022-06-13 7:35 ` Maxime Devos 2022-02-26 13:02 ` [bug#53878] [PATCH v5 05/22] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 06/22] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath 2022-02-26 14:19 ` Liliana Marie Prikler 2022-02-26 15:16 ` Philip McGrath 2022-02-26 15:19 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 07/22] gnu: racket-minimal: Add "debug" output Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 08/22] gnu: make-installation-layer.rkt: Adjust indentation Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 09/22] gnu: racket-minimal: Separate from the Racket VM Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 10/22] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath 2022-02-26 14:31 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 11/22] gnu: chez: Add utilities for Chez machine types Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 12/22] gnu: racket: Add 'racket-vm-for-system' Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 13/22] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-26 14:34 ` Liliana Marie Prikler 2022-02-26 13:02 ` [bug#53878] [PATCH v5 14/22] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 15/22] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 16/22] gnu: Add stex Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 17/22] gnu: Add chez-nanopass Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 18/22] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 19/22] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 20/22] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 21/22] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath 2022-02-26 13:02 ` [bug#53878] [PATCH v5 22/22] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 2022-02-26 15:08 ` [bug#53878] [PATCH v5 00/22] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler 2022-02-26 15:36 ` Philip McGrath 2022-02-26 16:14 ` Liliana Marie Prikler 2022-02-26 17:31 ` Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 00/24] " Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 02/24] gnu: racket: Update to 8.4 Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath 2022-02-27 8:42 ` Liliana Marie Prikler 2022-02-27 2:34 ` [bug#53878] [PATCH v6 04/24] gnu: racket-minimal: Use new package style Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-27 8:48 ` Liliana Marie Prikler 2022-02-27 2:34 ` [bug#53878] [PATCH v6 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 17/24] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 18/24] gnu: Add stex Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 19/24] gnu: Add chez-nanopass Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 22/24] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath 2022-02-27 2:34 ` [bug#53878] [PATCH v6 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 01/24] gnu: Use license prefix in (gnu packages racket) Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 02/24] gnu: racket: Update to 8.4 Philip McGrath 2022-02-27 21:28 ` [bug#53878] [PATCH v7 03/24] gnu: racket: Use Git origins for Racket packages Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 04/24] gnu: racket-minimal: Use new package style Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 05/24] gnu: racket-minimal: Don't configure non-existant catalogs Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 06/24] gnu: racket-minimal: Change inheritance to follow bootstrapping Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 07/24] gnu: racket-minimal: Adjust indentation Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 08/24] gnu: racket-minimal: Add "debug" output Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 09/24] gnu: configure-layer.rkt: Adjust indentation Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 10/24] gnu: racket-minimal: Separate from the Racket VM Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 11/24] gnu: racket: Move Chez bootfiles to (gnu packages chez) Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 12/24] gnu: chez: Add utilities for Chez machine types Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 13/24] gnu: racket: Add 'racket-vm-for-system' Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 14/24] gnu: chez-scheme: Use new style for Chez packages Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 15/24] gnu: chez-scheme: Use "lib/chez-scheme" for search path Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 16/24] gnu: chez-scheme: Use shared zlib and lz4 Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 17/24] gnu: chez-scheme: Use new package style Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 18/24] gnu: Add stex Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 19/24] gnu: Add chez-nanopass Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 20/24] gnu: chez-scheme: Explicitly package bootstrap bootfiles Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 21/24] gnu: chez-mit: Support chez-scheme-for-racket Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 22/24] gnu: Add chez-scheme-for-racket Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 23/24] gnu: chez: Add 'chez-scheme-for-system' Philip McGrath 2022-02-27 21:29 ` [bug#53878] [PATCH v7 24/24] gnu: racket-vm-cs: Build with "--enable-scheme" Philip McGrath 2022-03-04 22:59 ` bug#53878: [PATCH v7 00/24] Update Racket to 8.4. Adjust Chez Scheme packages Liliana Marie Prikler
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/guix.git 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).