aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-05-12 15:46:16 +0200
committerLudovic Courtès <ludo@gnu.org>2013-05-12 15:46:16 +0200
commitc0cd1b3ea7753fe2826f7a336019000df9dea96f (patch)
treea7e376f68216dcd26eab06aea5ff529b483fea00
parent9b1ef2f3232e7af111ba05353008ebd2f8955f02 (diff)
downloadgnu-guix-c0cd1b3ea7753fe2826f7a336019000df9dea96f.tar
gnu-guix-c0cd1b3ea7753fe2826f7a336019000df9dea96f.tar.gz
Move record utilities to (guix records).
* guix/utils.scm (define-record-type*): Move to... * guix/records.scm: ... here. New file. * guix/build-system.scm, guix/packages.scm: Use it. * guix/gnu-maintenance.scm: Likewise. (official-gnu-packages)[alist->record]: Remove. * guix/scripts/substitute-binary.scm: Likewise. (alist->record, object->fields): Remove. * tests/utils.scm ("define-record-type*", "define-record-type* with letrec* behavior", "define-record-type* & inherit", "define-record-type* & inherit & letrec* behavior", "define-record-type* & thunked", "define-record-type* & thunked & default", "define-record-type* & thunked & inherited"): Move to... * tests/records.scm: ... here. New file.
-rw-r--r--Makefile.am22
-rw-r--r--guix/build-system.scm4
-rw-r--r--guix/gnu-maintenance.scm7
-rw-r--r--guix/packages.scm1
-rw-r--r--guix/records.scm214
-rwxr-xr-xguix/scripts/substitute-binary.scm17
-rw-r--r--guix/utils.scm165
-rw-r--r--tests/records.scm137
-rw-r--r--tests/utils.scm108
9 files changed, 368 insertions, 307 deletions
diff --git a/Makefile.am b/Makefile.am
index 3998e9123f..69b4af013a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,6 +35,7 @@ MODULES = \
guix/scripts/substitute-binary.scm \
guix/scripts/refresh.scm \
guix/base32.scm \
+ guix/records.scm \
guix/utils.scm \
guix/serialization.scm \
guix/nar.scm \
@@ -85,7 +86,7 @@ MODULES = \
gnu/packages/cpio.scm \
gnu/packages/cppi.scm \
gnu/packages/cross-base.scm \
- gnu/packages/cryptsetup.scm \
+ gnu/packages/cryptsetup.scm \
gnu/packages/curl.scm \
gnu/packages/cyrus-sasl.scm \
gnu/packages/dejagnu.scm \
@@ -121,11 +122,11 @@ MODULES = \
gnu/packages/icu4c.scm \
gnu/packages/idutils.scm \
gnu/packages/indent.scm \
- gnu/packages/irssi.scm \
+ gnu/packages/irssi.scm \
gnu/packages/ld-wrapper.scm \
gnu/packages/less.scm \
gnu/packages/lesstif.scm \
- gnu/packages/libapr.scm \
+ gnu/packages/libapr.scm \
gnu/packages/libdaemon.scm \
gnu/packages/libevent.scm \
gnu/packages/libffi.scm \
@@ -156,7 +157,7 @@ MODULES = \
gnu/packages/ncurses.scm \
gnu/packages/netpbm.scm \
gnu/packages/nettle.scm \
- gnu/packages/ocaml.scm \
+ gnu/packages/ocaml.scm \
gnu/packages/oggvorbis.scm \
gnu/packages/openldap.scm \
gnu/packages/openssl.scm \
@@ -176,22 +177,22 @@ MODULES = \
gnu/packages/rsync.scm \
gnu/packages/samba.scm \
gnu/packages/scheme.scm \
- gnu/packages/screen.scm \
+ gnu/packages/screen.scm \
gnu/packages/shishi.scm \
gnu/packages/smalltalk.scm \
- gnu/packages/sqlite.scm \
+ gnu/packages/sqlite.scm \
gnu/packages/ssh.scm \
- gnu/packages/subversion.scm \
+ gnu/packages/subversion.scm \
gnu/packages/system.scm \
gnu/packages/tcl.scm \
- gnu/packages/tcsh.scm \
+ gnu/packages/tcsh.scm \
gnu/packages/texinfo.scm \
gnu/packages/texlive.scm \
gnu/packages/time.scm \
- gnu/packages/tmux.scm \
+ gnu/packages/tmux.scm \
gnu/packages/tor.scm \
gnu/packages/version-control.scm \
- gnu/packages/vim.scm \
+ gnu/packages/vim.scm \
gnu/packages/vpn.scm \
gnu/packages/w3m.scm \
gnu/packages/wdiff.scm \
@@ -313,6 +314,7 @@ SCM_TESTS = \
tests/builders.scm \
tests/derivations.scm \
tests/ui.scm \
+ tests/records.scm \
tests/utils.scm \
tests/build-utils.scm \
tests/packages.scm \
diff --git a/guix/build-system.scm b/guix/build-system.scm
index 0df5e4362b..c618a5e243 100644
--- a/guix/build-system.scm
+++ b/guix/build-system.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -17,7 +17,7 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix build-system)
- #:use-module (guix utils)
+ #:use-module (guix records)
#:export (build-system
build-system?
build-system-name
diff --git a/guix/gnu-maintenance.scm b/guix/gnu-maintenance.scm
index e39094db72..b54cd84ecf 100644
--- a/guix/gnu-maintenance.scm
+++ b/guix/gnu-maintenance.scm
@@ -32,6 +32,7 @@
#:use-module (guix ftp-client)
#:use-module (guix ui)
#:use-module (guix utils)
+ #:use-module (guix records)
#:use-module (guix packages)
#:use-module ((guix download) #:select (download-to-store))
#:use-module (guix gnupg)
@@ -150,12 +151,6 @@
(remove null-list? state)
(match-field line))))
- (define (alist->record alist make keys)
- ;; Apply MAKE, which should be a syntactic constructor, to the
- ;; values associated with KEYS in ALIST.
- (let ((args (map (cut assoc-ref alist <>) keys)))
- (apply make args)))
-
(reverse
(map (lambda (alist)
(alist->record alist
diff --git a/guix/packages.scm b/guix/packages.scm
index 1cbbd2ec47..0549771cea 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -18,6 +18,7 @@
(define-module (guix packages)
#:use-module (guix utils)
+ #:use-module (guix records)
#:use-module (guix store)
#:use-module (guix base32)
#:use-module (guix derivations)
diff --git a/guix/records.scm b/guix/records.scm
new file mode 100644
index 0000000000..54e1c17752
--- /dev/null
+++ b/guix/records.scm
@@ -0,0 +1,214 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; 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 (guix records)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 match)
+ #:export (define-record-type*
+ alist->record
+ object->fields))
+
+;;; Commentary:
+;;;
+;;; Utilities for dealing with Scheme records.
+;;;
+;;; Code:
+
+(define-syntax define-record-type*
+ (lambda (s)
+ "Define the given record type such that an additional \"syntactic
+constructor\" is defined, which allows instances to be constructed with named
+field initializers, à la SRFI-35, as well as default values."
+ (define (make-syntactic-constructor type name ctor fields thunked defaults)
+ "Make the syntactic constructor NAME for TYPE, that calls CTOR, and
+expects all of FIELDS to be initialized. DEFAULTS is the list of
+FIELD/DEFAULT-VALUE tuples, and THUNKED is the list of identifiers of
+thunked fields."
+ (with-syntax ((type type)
+ (name name)
+ (ctor ctor)
+ (expected fields)
+ (defaults defaults))
+ #`(define-syntax name
+ (lambda (s)
+ (define (record-inheritance orig-record field+value)
+ ;; Produce code that returns a record identical to
+ ;; ORIG-RECORD, except that values for the FIELD+VALUE alist
+ ;; prevail.
+ (define (field-inherited-value f)
+ (and=> (find (lambda (x)
+ (eq? f (car (syntax->datum x))))
+ field+value)
+ car))
+
+ #`(make-struct type 0
+ #,@(map (lambda (field index)
+ (or (field-inherited-value field)
+ #`(struct-ref #,orig-record
+ #,index)))
+ 'expected
+ (iota (length 'expected)))))
+
+ (define (thunked-field? f)
+ (memq (syntax->datum f) '#,thunked))
+
+ (define (field-bindings field+value)
+ ;; Return field to value bindings, for use in `letrec*' below.
+ (map (lambda (field+value)
+ (syntax-case field+value ()
+ ((field value)
+ #`(field
+ #,(if (thunked-field? #'field)
+ #'(lambda () value)
+ #'value)))))
+ field+value))
+
+ (syntax-case s (inherit #,@fields)
+ ((_ (inherit orig-record) (field value) (... ...))
+ #`(letrec* #,(field-bindings #'((field value) (... ...)))
+ #,(record-inheritance #'orig-record
+ #'((field value) (... ...)))))
+ ((_ (field value) (... ...))
+ (let ((fields (map syntax->datum #'(field (... ...))))
+ (dflt (map (match-lambda
+ ((f v)
+ (list (syntax->datum f) v)))
+ #'defaults)))
+
+ (define (field-value f)
+ (or (and=> (find (lambda (x)
+ (eq? f (car (syntax->datum x))))
+ #'((field value) (... ...)))
+ car)
+ (let ((value
+ (car (assoc-ref dflt
+ (syntax->datum f)))))
+ (if (thunked-field? f)
+ #`(lambda () #,value)
+ value))))
+
+ (let-syntax ((error*
+ (syntax-rules ()
+ ((_ fmt args (... ...))
+ (syntax-violation 'name
+ (format #f fmt args
+ (... ...))
+ s)))))
+ (let ((fields (append fields (map car dflt))))
+ (cond ((lset= eq? fields 'expected)
+ #`(letrec* #,(field-bindings
+ #'((field value) (... ...)))
+ (ctor #,@(map field-value 'expected))))
+ ((pair? (lset-difference eq? fields 'expected))
+ (error* "extraneous field initializers ~a"
+ (lset-difference eq? fields 'expected)))
+ (else
+ (error* "missing field initializers ~a"
+ (lset-difference eq? 'expected
+ fields)))))))))))))
+
+ (define (field-default-value s)
+ (syntax-case s (default)
+ ((field (default val) _ ...)
+ (list #'field #'val))
+ ((field _ options ...)
+ (field-default-value #'(field options ...)))
+ (_ #f)))
+
+ (define (thunked-field? s)
+ ;; Return the field name if the field defined by S is thunked.
+ (syntax-case s (thunked)
+ ((field (thunked) _ ...)
+ #'field)
+ ((field _ options ...)
+ (thunked-field? #'(field options ...)))
+ (_ #f)))
+
+ (define (thunked-field-accessor-name field)
+ ;; Return the name (an unhygienic syntax object) of the "real"
+ ;; getter for field, which is assumed to be a thunked field.
+ (syntax-case field ()
+ ((field get options ...)
+ (let* ((getter (syntax->datum #'get))
+ (real-getter (symbol-append '% getter '-real)))
+ (datum->syntax #'get real-getter)))))
+
+ (define (field-spec->srfi-9 field)
+ ;; Convert a field spec of our style to a SRFI-9 field spec of the
+ ;; form (field get).
+ (syntax-case field ()
+ ((name get options ...)
+ #`(name
+ #,(if (thunked-field? field)
+ (thunked-field-accessor-name field)
+ #'get)))))
+
+ (define (thunked-field-accessor-definition field)
+ ;; Return the real accessor for FIELD, which is assumed to be a
+ ;; thunked field.
+ (syntax-case field ()
+ ((name get _ ...)
+ (with-syntax ((real-get (thunked-field-accessor-name field)))
+ #'(define-inlinable (get x)
+ ;; The real value of that field is a thunk, so call it.
+ ((real-get x)))))))
+
+ (syntax-case s ()
+ ((_ type syntactic-ctor ctor pred
+ (field get options ...) ...)
+ (let* ((field-spec #'((field get options ...) ...)))
+ (with-syntax (((field-spec* ...)
+ (map field-spec->srfi-9 field-spec))
+ ((thunked-field-accessor ...)
+ (filter-map (lambda (field)
+ (and (thunked-field? field)
+ (thunked-field-accessor-definition
+ field)))
+ field-spec)))
+ #`(begin
+ (define-record-type type
+ (ctor field ...)
+ pred
+ field-spec* ...)
+ (begin thunked-field-accessor ...)
+ #,(make-syntactic-constructor #'type #'syntactic-ctor #'ctor
+ #'(field ...)
+ (filter-map thunked-field? field-spec)
+ (filter-map field-default-value
+ #'((field options ...)
+ ...))))))))))
+
+(define (alist->record alist make keys)
+ "Apply MAKE to the values associated with KEYS in ALIST."
+ (let ((args (map (cut assoc-ref alist <>) keys)))
+ (apply make args)))
+
+(define (object->fields object fields port)
+ "Write OBJECT (typically a record) as a series of recutils-style fields to
+PORT, according to FIELDS. FIELDS must be a list of field name/getter pairs."
+ (let loop ((fields fields))
+ (match fields
+ (()
+ object)
+ (((field . get) rest ...)
+ (format port "~a: ~a~%" field (get object))
+ (loop rest)))))
+
+;;; records.scm ends here
diff --git a/guix/scripts/substitute-binary.scm b/guix/scripts/substitute-binary.scm
index 995078e630..5965e936f9 100755
--- a/guix/scripts/substitute-binary.scm
+++ b/guix/scripts/substitute-binary.scm
@@ -21,6 +21,7 @@
#:use-module (guix store)
#:use-module (guix utils)
#:use-module (guix config)
+ #:use-module (guix records)
#:use-module (guix nar)
#:use-module ((guix build utils) #:select (mkdir-p))
#:use-module (ice-9 rdelim)
@@ -103,22 +104,6 @@ pairs."
(else
(error "unmatched line" line)))))
-(define (alist->record alist make keys)
- "Apply MAKE to the values associated with KEYS in ALIST."
- (let ((args (map (cut assoc-ref alist <>) keys)))
- (apply make args)))
-
-(define (object->fields object fields port)
- "Write OBJECT (typically a record) as a series of recutils-style fields to
-PORT, according to FIELDS. FIELDS must be a list of field name/getter pairs."
- (let loop ((fields fields))
- (match fields
- (()
- object)
- (((field . get) rest ...)
- (format port "~a: ~a~%" field (get object))
- (loop rest)))))
-
(define (fetch uri)
"Return a binary input port to URI and the number of bytes it's expected to
provide."
diff --git a/guix/utils.scm b/guix/utils.scm
index 7c8e914c01..c2d2808f76 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -42,7 +42,6 @@
nixpkgs-derivation
nixpkgs-derivation*
- define-record-type*
compile-time-value
memoize
default-keyword-arguments
@@ -239,170 +238,6 @@ wait."
;;; Miscellaneous.
;;;
-(define-syntax define-record-type*
- (lambda (s)
- "Define the given record type such that an additional \"syntactic
-constructor\" is defined, which allows instances to be constructed with named
-field initializers, à la SRFI-35, as well as default values."
- (define (make-syntactic-constructor type name ctor fields thunked defaults)
- "Make the syntactic constructor NAME for TYPE, that calls CTOR, and
-expects all of FIELDS to be initialized. DEFAULTS is the list of
-FIELD/DEFAULT-VALUE tuples, and THUNKED is the list of identifiers of
-thunked fields."
- (with-syntax ((type type)
- (name name)
- (ctor ctor)
- (expected fields)
- (defaults defaults))
- #`(define-syntax name
- (lambda (s)
- (define (record-inheritance orig-record field+value)
- ;; Produce code that returns a record identical to
- ;; ORIG-RECORD, except that values for the FIELD+VALUE alist
- ;; prevail.
- (define (field-inherited-value f)
- (and=> (find (lambda (x)
- (eq? f (car (syntax->datum x))))
- field+value)
- car))
-
- #`(make-struct type 0
- #,@(map (lambda (field index)
- (or (field-inherited-value field)
- #`(struct-ref #,orig-record
- #,index)))
- 'expected
- (iota (length 'expected)))))
-
- (define (thunked-field? f)
- (memq (syntax->datum f) '#,thunked))
-
- (define (field-bindings field+value)
- ;; Return field to value bindings, for use in `letrec*' below.
- (map (lambda (field+value)
- (syntax-case field+value ()
- ((field value)
- #`(field
- #,(if (thunked-field? #'field)
- #'(lambda () value)
- #'value)))))
- field+value))
-
- (syntax-case s (inherit #,@fields)
- ((_ (inherit orig-record) (field value) (... ...))
- #`(letrec* #,(field-bindings #'((field value) (... ...)))
- #,(record-inheritance #'orig-record
- #'((field value) (... ...)))))
- ((_ (field value) (... ...))
- (let ((fields (map syntax->datum #'(field (... ...))))
- (dflt (map (match-lambda
- ((f v)
- (list (syntax->datum f) v)))
- #'defaults)))
-
- (define (field-value f)
- (or (and=> (find (lambda (x)
- (eq? f (car (syntax->datum x))))
- #'((field value) (... ...)))
- car)
- (let ((value
- (car (assoc-ref dflt
- (syntax->datum f)))))
- (if (thunked-field? f)
- #`(lambda () #,value)
- value))))
-
- (let-syntax ((error*
- (syntax-rules ()
- ((_ fmt args (... ...))
- (syntax-violation 'name
- (format #f fmt args
- (... ...))
- s)))))
- (let ((fields (append fields (map car dflt))))
- (cond ((lset= eq? fields 'expected)
- #`(letrec* #,(field-bindings
- #'((field value) (... ...)))
- (ctor #,@(map field-value 'expected))))
- ((pair? (lset-difference eq? fields 'expected))
- (error* "extraneous field initializers ~a"
- (lset-difference eq? fields 'expected)))
- (else
- (error* "missing field initializers ~a"
- (lset-difference eq? 'expected
- fields)))))))))))))
-
- (define (field-default-value s)
- (syntax-case s (default)
- ((field (default val) _ ...)
- (list #'field #'val))
- ((field _ options ...)
- (field-default-value #'(field options ...)))
- (_ #f)))
-
- (define (thunked-field? s)
- ;; Return the field name if the field defined by S is thunked.
- (syntax-case s (thunked)
- ((field (thunked) _ ...)
- #'field)
- ((field _ options ...)
- (thunked-field? #'(field options ...)))
- (_ #f)))
-
- (define (thunked-field-accessor-name field)
- ;; Return the name (an unhygienic syntax object) of the "real"
- ;; getter for field, which is assumed to be a thunked field.
- (syntax-case field ()
- ((field get options ...)
- (let* ((getter (syntax->datum #'get))
- (real-getter (symbol-append '% getter '-real)))
- (datum->syntax #'get real-getter)))))
-
- (define (field-spec->srfi-9 field)
- ;; Convert a field spec of our style to a SRFI-9 field spec of the
- ;; form (field get).
- (syntax-case field ()
- ((name get options ...)
- #`(name
- #,(if (thunked-field? field)
- (thunked-field-accessor-name field)
- #'get)))))
-
- (define (thunked-field-accessor-definition field)
- ;; Return the real accessor for FIELD, which is assumed to be a
- ;; thunked field.
- (syntax-case field ()
- ((name get _ ...)
- (with-syntax ((real-get (thunked-field-accessor-name field)))
- #'(define-inlinable (get x)
- ;; The real value of that field is a thunk, so call it.
- ((real-get x)))))))
-
- (syntax-case s ()
- ((_ type syntactic-ctor ctor pred
- (field get options ...) ...)
- (let* ((field-spec #'((field get options ...) ...)))
- (with-syntax (((field-spec* ...)
- (map field-spec->srfi-9 field-spec))
- ((thunked-field-accessor ...)
- (filter-map (lambda (field)
- (and (thunked-field? field)
- (thunked-field-accessor-definition
- field)))
- field-spec)))
- #`(begin
- (define-record-type type
- (ctor field ...)
- pred
- field-spec* ...)
- (begin thunked-field-accessor ...)
- #,(make-syntactic-constructor #'type #'syntactic-ctor #'ctor
- #'(field ...)
- (filter-map thunked-field? field-spec)
- (filter-map field-default-value
- #'((field options ...)
- ...))))))))))
-
(define (memoize proc)
"Return a memoizing version of PROC."
(let ((cache (make-hash-table)))
diff --git a/tests/records.scm b/tests/records.scm
new file mode 100644
index 0000000000..9e524b670c
--- /dev/null
+++ b/tests/records.scm
@@ -0,0 +1,137 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; 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 (test-records)
+ #:use-module (srfi srfi-64)
+ #:use-module (ice-9 match)
+ #:use-module (guix records))
+
+(test-begin "records")
+
+(test-assert "define-record-type*"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar)
+ (baz foo-baz (default (+ 40 2))))
+ (and (match (foo (bar 1) (baz 2))
+ (($ <foo> 1 2) #t))
+ (match (foo (baz 2) (bar 1))
+ (($ <foo> 1 2) #t))
+ (match (foo (bar 1))
+ (($ <foo> 1 42) #t)))))
+
+(test-assert "define-record-type* with letrec* behavior"
+ ;; Make sure field initializers can refer to each other as if they were in
+ ;; a `letrec*'.
+ (begin
+ (define-record-type* <bar> bar make-bar
+ foo?
+ (x bar-x)
+ (y bar-y (default (+ 40 2)))
+ (z bar-z))
+ (and (match (bar (x 1) (y (+ x 1)) (z (* y 2)))
+ (($ <bar> 1 2 4) #t))
+ (match (bar (x 7) (z (* x 3)))
+ (($ <bar> 7 42 21)))
+ (match (bar (z 21) (x (/ z 3)))
+ (($ <bar> 7 42 21))))))
+
+(test-assert "define-record-type* & inherit"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar)
+ (baz foo-baz (default (+ 40 2))))
+ (let* ((a (foo (bar 1)))
+ (b (foo (inherit a) (baz 2)))
+ (c (foo (inherit b) (bar -2)))
+ (d (foo (inherit c)))
+ (e (foo (inherit (foo (bar 42))) (baz 77))))
+ (and (match a (($ <foo> 1 42) #t))
+ (match b (($ <foo> 1 2) #t))
+ (match c (($ <foo> -2 2) #t))
+ (equal? c d)
+ (match e (($ <foo> 42 77) #t))))))
+
+(test-assert "define-record-type* & inherit & letrec* behavior"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar)
+ (baz foo-baz (default (+ 40 2))))
+ (let* ((a (foo (bar 77)))
+ (b (foo (inherit a) (bar 1) (baz (+ bar 1))))
+ (c (foo (inherit b) (baz 2) (bar (- baz 1)))))
+ (and (match a (($ <foo> 77 42) #t))
+ (match b (($ <foo> 1 2) #t))
+ (equal? b c)))))
+
+(test-assert "define-record-type* & thunked"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar)
+ (baz foo-baz (thunked)))
+
+ (let* ((calls 0)
+ (x (foo (bar 2)
+ (baz (begin (set! calls (1+ calls)) 3)))))
+ (and (zero? calls)
+ (equal? (foo-bar x) 2)
+ (equal? (foo-baz x) 3) (= 1 calls)
+ (equal? (foo-baz x) 3) (= 2 calls)))))
+
+(test-assert "define-record-type* & thunked & default"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar)
+ (baz foo-baz (thunked) (default 42)))
+
+ (let ((mark (make-parameter #f)))
+ (let ((x (foo (bar 2) (baz (mark))))
+ (y (foo (bar 2))))
+ (and (equal? (foo-bar x) 2)
+ (parameterize ((mark (cons 'a 'b)))
+ (eq? (foo-baz x) (mark)))
+ (equal? (foo-bar y) 2)
+ (equal? (foo-baz y) 42))))))
+
+(test-assert "define-record-type* & thunked & inherited"
+ (begin
+ (define-record-type* <foo> foo make-foo
+ foo?
+ (bar foo-bar (thunked))
+ (baz foo-baz (thunked) (default 42)))
+
+ (let ((mark (make-parameter #f)))
+ (let* ((x (foo (bar 2) (baz (mark))))
+ (y (foo (inherit x) (bar (mark)))))
+ (and (equal? (foo-bar x) 2)
+ (parameterize ((mark (cons 'a 'b)))
+ (eq? (foo-baz x) (mark)))
+ (parameterize ((mark (cons 'a 'b)))
+ (eq? (foo-bar y) (mark)))
+ (parameterize ((mark (cons 'a 'b)))
+ (eq? (foo-baz y) (mark))))))))
+
+(test-end)
+
+
+(exit (= (test-runner-fail-count (test-runner-current)) 0))
diff --git a/tests/utils.scm b/tests/utils.scm
index f14412e61e..c2fb274193 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -126,114 +126,6 @@
(append pids1 pids2)))
(equal? (get-bytevector-all decompressed) data)))))
-(test-assert "define-record-type*"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar)
- (baz foo-baz (default (+ 40 2))))
- (and (match (foo (bar 1) (baz 2))
- (($ <foo> 1 2) #t))
- (match (foo (baz 2) (bar 1))
- (($ <foo> 1 2) #t))
- (match (foo (bar 1))
- (($ <foo> 1 42) #t)))))
-
-(test-assert "define-record-type* with letrec* behavior"
- ;; Make sure field initializers can refer to each other as if they were in
- ;; a `letrec*'.
- (begin
- (define-record-type* <bar> bar make-bar
- foo?
- (x bar-x)
- (y bar-y (default (+ 40 2)))
- (z bar-z))
- (and (match (bar (x 1) (y (+ x 1)) (z (* y 2)))
- (($ <bar> 1 2 4) #t))
- (match (bar (x 7) (z (* x 3)))
- (($ <bar> 7 42 21)))
- (match (bar (z 21) (x (/ z 3)))
- (($ <bar> 7 42 21))))))
-
-(test-assert "define-record-type* & inherit"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar)
- (baz foo-baz (default (+ 40 2))))
- (let* ((a (foo (bar 1)))
- (b (foo (inherit a) (baz 2)))
- (c (foo (inherit b) (bar -2)))
- (d (foo (inherit c)))
- (e (foo (inherit (foo (bar 42))) (baz 77))))
- (and (match a (($ <foo> 1 42) #t))
- (match b (($ <foo> 1 2) #t))
- (match c (($ <foo> -2 2) #t))
- (equal? c d)
- (match e (($ <foo> 42 77) #t))))))
-
-(test-assert "define-record-type* & inherit & letrec* behavior"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar)
- (baz foo-baz (default (+ 40 2))))
- (let* ((a (foo (bar 77)))
- (b (foo (inherit a) (bar 1) (baz (+ bar 1))))
- (c (foo (inherit b) (baz 2) (bar (- baz 1)))))
- (and (match a (($ <foo> 77 42) #t))
- (match b (($ <foo> 1 2) #t))
- (equal? b c)))))
-
-(test-assert "define-record-type* & thunked"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar)
- (baz foo-baz (thunked)))
-
- (let* ((calls 0)
- (x (foo (bar 2)
- (baz (begin (set! calls (1+ calls)) 3)))))
- (and (zero? calls)
- (equal? (foo-bar x) 2)
- (equal? (foo-baz x) 3) (= 1 calls)
- (equal? (foo-baz x) 3) (= 2 calls)))))
-
-(test-assert "define-record-type* & thunked & default"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar)
- (baz foo-baz (thunked) (default 42)))
-
- (let ((mark (make-parameter #f)))
- (let ((x (foo (bar 2) (baz (mark))))
- (y (foo (bar 2))))
- (and (equal? (foo-bar x) 2)
- (parameterize ((mark (cons 'a 'b)))
- (eq? (foo-baz x) (mark)))
- (equal? (foo-bar y) 2)
- (equal? (foo-baz y) 42))))))
-
-(test-assert "define-record-type* & thunked & inherited"
- (begin
- (define-record-type* <foo> foo make-foo
- foo?
- (bar foo-bar (thunked))
- (baz foo-baz (thunked) (default 42)))
-
- (let ((mark (make-parameter #f)))
- (let* ((x (foo (bar 2) (baz (mark))))
- (y (foo (inherit x) (bar (mark)))))
- (and (equal? (foo-bar x) 2)
- (parameterize ((mark (cons 'a 'b)))
- (eq? (foo-baz x) (mark)))
- (parameterize ((mark (cons 'a 'b)))
- (eq? (foo-bar y) (mark)))
- (parameterize ((mark (cons 'a 'b)))
- (eq? (foo-baz y) (mark))))))))
-
;; This is actually in (guix store).
(test-equal "store-path-package-name"
"bash-4.2-p24"