Hi Mario, I think this would be a bit cleaner if it didn't rely on data-structures. If I understand correctly, you're only using it for "complement", which is trivial to implement directly.
I'm also not sure if the make rule is correct as-is, since it doesn't depend on data-structures. Cheers, Peter On Fri, Oct 03, 2025 at 08:40:38PM +0200, Mario Domenech Goulart via Chicken-hackers wrote: > Hi, > > The attached patch adds the chicken.version module to CHICKEN, > addressing https://bugs.call-cc.org/ticket/1823 . > > It basically exposes the version>=? procedure used by chicken-install > through a module, as that procedure tends useful for eggs and ends up > being copied, as CHICKEN does not make it available. > > Because it was easy, I've added version<? to the module as well (it's > the complement of version>=?). Maybe we can add a more complete set of > comparators before releasing C6. > > All the best. > Mario > -- > https://parenteses.org/mario > From 97287bcc84d7638b2acc61fb570ae7d41012a7db Mon Sep 17 00:00:00 2001 > From: Mario Domenech Goulart <[email protected]> > Date: Sun, 28 Sep 2025 10:15:15 +0200 > Subject: [PATCH] Add chicken.version module > > Addresses #1823 > --- > .gitignore | 2 + > NEWS | 1 + > README | 1 + > chicken-install.scm | 21 +--------- > defaults.make | 2 +- > distribution/manifest | 6 +++ > eval-modules.scm | 1 + > eval.scm | 2 +- > manual/Included modules | 1 + > manual/Module (chicken type) | 2 +- > manual/Module (chicken version) | 26 ++++++++++++ > manual/Module srfi-4 | 2 +- > rules.make | 8 +++- > tests/runtests.sh | 3 ++ > tests/types-db-consistency.scm | 1 + > tests/version-module-tests.scm | 32 +++++++++++++++ > types.db | 4 ++ > version.scm | 71 +++++++++++++++++++++++++++++++++ > 18 files changed, 161 insertions(+), 25 deletions(-) > create mode 100644 manual/Module (chicken version) > create mode 100644 tests/version-module-tests.scm > create mode 100644 version.scm > > diff --git a/.gitignore b/.gitignore > index 202db4f9..fe31a320 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -74,6 +74,7 @@ > /support.c > /tcp.c > /user-pass.c > +/version.c > > # Compiled Scheme modules' imports > > @@ -123,6 +124,7 @@ > /chicken.string.import.scm > /chicken.tcp.import.scm > /chicken.time.posix.import.scm > +/chicken.version.import.scm > /chicken.number-vector.import.scm > /srfi-4.import.scm > /scheme.write.import.scm > diff --git a/NEWS b/NEWS > index 86c4caf8..ea72b5b7 100644 > --- a/NEWS > +++ b/NEWS > @@ -80,6 +80,7 @@ > separation. > - Added `expand1' to (chicken syntax) module for expanding a macro > only once, also added the ",x1" command to "csi" for this. > + - Added the (chicken version) module. > > - Syntax expander: > - `syntax-rules' attempts to better support tail patterns with ellipses > diff --git a/README b/README > index 7b80992c..4571a3e3 100644 > --- a/README > +++ b/README > @@ -342,6 +342,7 @@ _/ _/ _/ _/ _/ _/ _/ _/ > _/ _/_/ > | | |-- chicken.tcp.import.so > | | |-- chicken.time.import.so > | | |-- chicken.time.posix.import.so > + | | |-- chicken.version.import.so > | | |-- scheme.file.import.so > | | |-- scheme.process-context.import.so > | | |-- scheme.time.import.so > diff --git a/chicken-install.scm b/chicken-install.scm > index 32a5bf9f..bfcfa794 100644 > --- a/chicken-install.scm > +++ b/chicken-install.scm > @@ -54,6 +54,7 @@ > (import (chicken pretty-print)) > (import (chicken string)) > (import (chicken bytevector)) > +(import (chicken version)) > (import (only (scheme base) open-input-string)) > > (define +defaults-version+ 2) > @@ -267,26 +268,6 @@ > (apply fprintf port fstr args) > (flush-output port) ) ))) > > -(define (version>=? v1 v2) > - (define (version->list v) > - (map (lambda (x) (or (string->number x) x)) > - (irregex-split "[-\\._]" (->string v)))) > - (let loop ((p1 (version->list v1)) > - (p2 (version->list v2))) > - (cond ((null? p1) (null? p2)) > - ((null? p2)) > - ((number? (car p1)) > - (and (number? (car p2)) > - (or (> (car p1) (car p2)) > - (and (= (car p1) (car p2)) > - (loop (cdr p1) (cdr p2)))))) > - ((number? (car p2))) > - ((string>? (car p1) (car p2))) > - (else > - (and (string=? (car p1) (car p2)) > - (loop (cdr p1) (cdr p2))))))) > - > - > ;; load defaults file ("setup.defaults") > > (define (load-defaults) > diff --git a/defaults.make b/defaults.make > index 5ff724ce..eecc0e0e 100644 > --- a/defaults.make > +++ b/defaults.make > @@ -275,7 +275,7 @@ DYNAMIC_CHICKEN_IMPORT_LIBRARIES = bitwise bytevector > errno file.posix \ > random sort string time.posix number-vector > DYNAMIC_CHICKEN_COMPILER_IMPORT_LIBRARIES = user-pass > DYNAMIC_CHICKEN_UNIT_IMPORT_LIBRARIES = continuation eval file \ > - internal irregex pathname port read-syntax repl tcp > + internal irregex pathname port read-syntax repl tcp version > > # targets > > diff --git a/distribution/manifest b/distribution/manifest > index d19d2fdd..46ffee41 100644 > --- a/distribution/manifest > +++ b/distribution/manifest > @@ -102,6 +102,8 @@ read-syntax.scm > repl.scm > runtime.c > utf.c > +version.c > +version.scm > scheduler.scm > srfi-4.scm > stub.scm > @@ -251,6 +253,7 @@ tests/reverser/tags/1.1/reverser.egg > tests/reverser/tags/1.1/reverser.scm > tests/user-pass-tests.scm > tests/version-tests.scm > +tests/version-module-tests.scm > tests/messages-test.scm > tests/messages.expected > tests/types-db-consistency.scm > @@ -379,6 +382,8 @@ chicken.time.import.scm > chicken.time.import.c > chicken.time.posix.import.scm > chicken.time.posix.import.c > +chicken.version.import.scm > +chicken.version.import.c > srfi-4.import.scm > srfi-4.import.c > scheme.file.import.scm > @@ -476,6 +481,7 @@ manual-html/Module (chicken tcp).html > manual-html/Module (chicken time).html > manual-html/Module (chicken time posix).html > manual-html/Module (chicken type).html > +manual-html/Module (chicken version).html > manual-html/Module scheme.html > manual-html/Module (scheme base).html > manual-html/Module (scheme case-lambda).html > diff --git a/eval-modules.scm b/eval-modules.scm > index 5c4ed095..fdae737a 100644 > --- a/eval-modules.scm > +++ b/eval-modules.scm > @@ -92,6 +92,7 @@ > (defmod chicken.read-syntax) > (defmod chicken.repl) > (defmod chicken.tcp) > +(defmod chicken.version) > (defmod chicken.number-vector) > (defmod srfi-4) > (defmod scheme.write) > diff --git a/eval.scm b/eval.scm > index 64a9bbda..1f211f07 100644 > --- a/eval.scm > +++ b/eval.scm > @@ -946,7 +946,7 @@ > '(chicken-syntax chicken-ffi-syntax continuation data-structures > debugger-client eval eval-modules expand extras file internal > irregex library lolevel pathname port posix profiler read-syntax > - repl scheduler srfi-4 tcp r7lib)) > + repl scheduler srfi-4 tcp r7lib version)) > > (define-constant cygwin-default-dynamic-load-libraries '("cygchicken-0")) > (define-constant macosx-load-library-extension ".dylib") > diff --git a/manual/Included modules b/manual/Included modules > index b2390d46..db2cffa4 100644 > --- a/manual/Included modules > +++ b/manual/Included modules > @@ -74,6 +74,7 @@ default all exports of the [[Module scheme|scheme]], > * [[Module (chicken time)]] : Fetching information about the current time > * [[Module (chicken time posix)]] : Manipulating POSIX time > * [[Module (chicken type)]] : Defining and using static typing information > +* [[Module (chicken version)]] : Version comparison operations > * [[Module srfi-4]] : The subset of [[Module (chicken number-vector)]] > specified by SRFI-4 > > In addition to the core modules listed above, the following SRFI modules can > be > diff --git a/manual/Module (chicken type) b/manual/Module (chicken type) > index 9673dde7..46f6b128 100644 > --- a/manual/Module (chicken type) > +++ b/manual/Module (chicken type) > @@ -9,4 +9,4 @@ The functionality in this module is available by default. See > --- > Previous: [[Module (chicken time posix)]] > > -Next: [[Module srfi-4]] > +Next: [[Module (chicken version)]] > diff --git a/manual/Module (chicken version) b/manual/Module (chicken version) > new file mode 100644 > index 00000000..2b5a1369 > --- /dev/null > +++ b/manual/Module (chicken version) > @@ -0,0 +1,26 @@ > +[[tags: manual]] > +[[toc:]] > + > +== Module (chicken version) > + > +This module contains procedures for version comparison operations. > + > +=== version>=? > + > +<procedure>(version>=? v1 v2)</procedure> > + > +Return {{#t}} if {{v1}} is greater than or equal to {{v2}}. Arguments > +can be of any type and internally will be converted to strings. > + > +=== version<? > + > +<procedure>(version<? v1 v2)</procedure> > + > +The complement of {{version>=?}}. Return {{#t}} if {{v1}} is less > +than {{v2}}. Arguments can be of any type and internally will be > +converted to strings. > + > +--- > +Previous: [[Module (chicken type)]] > + > +Next: [[Module srfi-4]] > diff --git a/manual/Module srfi-4 b/manual/Module srfi-4 > index dcd18afb..6493af03 100644 > --- a/manual/Module srfi-4 > +++ b/manual/Module srfi-4 > @@ -93,7 +93,7 @@ The module exports the following identifiers: > <procedure>(list->f64vector F64LIST)</procedure><br> > > --- > -Previous: [[Module (chicken type)]] > +Previous: [[Module (chicken version)]] > > Next: [[Interface to external functions and variables]] > > diff --git a/rules.make b/rules.make > index 86a5e7eb..ce8f9701 100644 > --- a/rules.make > +++ b/rules.make > @@ -37,7 +37,7 @@ LIBCHICKEN_SCHEME_OBJECTS_1 = \ > library eval read-syntax repl data-structures pathname port file \ > extras lolevel tcp srfi-4 continuation $(POSIXFILE) internal \ > irregex scheduler debugger-client profiler stub expand modules \ > - chicken-syntax chicken-ffi-syntax build-version r7lib > + chicken-syntax chicken-ffi-syntax build-version r7lib version > LIBCHICKEN_OBJECTS_1 = $(LIBCHICKEN_SCHEME_OBJECTS_1) runtime utf > LIBCHICKEN_SHARED_OBJECTS = $(LIBCHICKEN_OBJECTS_1:=$(O)) > LIBCHICKEN_STATIC_OBJECTS = $(LIBCHICKEN_OBJECTS_1:=-static$(O)) \ > @@ -681,6 +681,7 @@ chicken-install.c: chicken-install.scm \ > chicken.process-context.import.scm \ > chicken.sort.import.scm \ > chicken.string.import.scm \ > + chicken.version.import.scm \ > chicken.tcp.import.scm > chicken-uninstall.c: chicken-uninstall.scm \ > chicken.file.import.scm \ > @@ -779,6 +780,9 @@ tcp.c: tcp.scm \ > chicken.foreign.import.scm \ > chicken.port.import.scm \ > chicken.time.import.scm > +version.c: version.scm \ > + chicken.irregex.import.scm \ > + chicken.string.import.scm > eval-modules.c: eval-modules.scm $(DYNAMIC_IMPORT_LIBRARIES:=.import.scm) \ > $(foreach > lib,$(DYNAMIC_CHICKEN_IMPORT_LIBRARIES),chicken.$(lib).import.scm) \ > $(foreach lib,$(DYNAMIC_CHICKEN_UNIT_IMPORT_LIBRARIES),$(lib).c) > @@ -887,6 +891,8 @@ lolevel.c: $(SRCDIR)lolevel.scm > $(SRCDIR)common-declarations.scm > -emit-import-library chicken.memory.representation > tcp.c: $(SRCDIR)tcp.scm $(SRCDIR)common-declarations.scm > $(bootstrap-lib) -emit-import-library chicken.tcp > +version.c: $(SRCDIR)version.scm $(SRCDIR)common-declarations.scm > + $(bootstrap-lib) -emit-import-library chicken.version > srfi-4.c: $(SRCDIR)srfi-4.scm $(SRCDIR)common-declarations.scm > $(bootstrap-lib) -emit-import-library srfi-4 \ > -emit-import-library chicken.number-vector > diff --git a/tests/runtests.sh b/tests/runtests.sh > index c3ad34a7..1422ce51 100755 > --- a/tests/runtests.sh > +++ b/tests/runtests.sh > @@ -554,4 +554,7 @@ $interpret -s multiple-values.scm > $compile multiple-values.scm > ./a.out > > +echo "======================================== version module tests ..." > +$interpret -bnq version-module-tests.scm > + > echo "======================================== done. All tests passed." > diff --git a/tests/types-db-consistency.scm b/tests/types-db-consistency.scm > index a7e391ed..8e00004c 100644 > --- a/tests/types-db-consistency.scm > +++ b/tests/types-db-consistency.scm > @@ -14,6 +14,7 @@ > (chicken process-context posix) > (chicken tcp) > (chicken number-vector) > + (chicken version) > (scheme write)) > > (define ignored-symbols > diff --git a/tests/version-module-tests.scm b/tests/version-module-tests.scm > new file mode 100644 > index 00000000..a309fc5a > --- /dev/null > +++ b/tests/version-module-tests.scm > @@ -0,0 +1,32 @@ > +(import (chicken eval) > + (chicken load) > + (chicken version)) > + > +(cond-expand > + (compiling > + (include "test.scm") ) > + (else > + (load-relative "test.scm"))) > + > +(test-begin "chicken.version") > + > +(test-assert "0 >= 0" (version>=? "0" "0")) > +(test-assert "1 >= 0" (version>=? "1" "0")) > +(test-assert "1.0 >= 0.0.1" (version>=? "1.0" "0.0.1")) > +(test-assert "1.0 >= 0.1.1" (version>=? "1.0" "0.1.1")) > +(test-assert "0.0.0 >= 0.0.0" (version>=? "0.0.0" "0.0.0")) > +(test-assert "0.0.0 >= 0.0" (version>=? "0.0.0" "0.0")) > +(test-assert "0.0.1 >= 0.0.0" (version>=? "0.0.1" "0.0.0")) > +(test-assert "1.0.0 >= 0.0.0" (version>=? "1.0.0" "0.0.0")) > +(test-assert "1.0.0 >= 0.0.0b" (version>=? "1.0.0" "0.0.0b")) > +(test-assert "1.0.0b >= 1.0.0" (version>=? "1.0.0b" "1.0.0")) > +(test-assert "1.0.0 >= 0.9.9-rc1" (version>=? "1.0.0" "0.9.9-rc1")) > +(test-assert "1.10 >= 1.09" (version>=? "1.10" "1.09")) > +(test-assert "(numbers) 0 >= 0" (version>=? 0 0)) > +(test-assert "(numbers) 1 >= 0" (version>=? 1 0)) > +(test-assert "(numbers) 1.09 >= 1.10" (version>=? 1.09 1.10)) > + > +;; Just to make sure that the module exports this procedure > +(test-assert "0 < 1" (version<? "0" "1")) > + > +(test-end "chicken.version") > diff --git a/types.db b/types.db > index fba0eaa6..5278fc88 100644 > --- a/types.db > +++ b/types.db > @@ -2461,6 +2461,10 @@ > (chicken.tcp#tcp-read-timeout (#(procedure #:clean #:enforce) > chicken.tcp#tcp-read-timeout (#!optional (or false integer)) (or false > integer))) > (chicken.tcp#tcp-write-timeout (#(procedure #:clean #:enforce) > chicken.tcp#tcp-write-timeout (#!optional (or false integer)) (or false > integer))) > > +;; version > +(chicken.version#version>=? (#(procedure #:pure #:foldable) > chicken.version#version>=? (* *) boolean)) > +(chicken.version#version<? (#(procedure #:pure #:foldable) > chicken.version#version<? (* *) boolean)) > + > ;; Undocumented internal module, only here to have the deprecation warning > because some eggs use it > (chicken.compiler.support#read/source-info deprecated) > > diff --git a/version.scm b/version.scm > new file mode 100644 > index 00000000..c3aea035 > --- /dev/null > +++ b/version.scm > @@ -0,0 +1,71 @@ > +;;;; version.scm > +; > +; Copyright (c) 2025, The CHICKEN Team > +; All rights reserved. > +; > +; Redistribution and use in source and binary forms, with or without > +; modification, are permitted provided that the following conditions > +; are met: > +; > +; Redistributions of source code must retain the above copyright > +; notice, this list of conditions and the following disclaimer. > +; > +; Redistributions in binary form must reproduce the above copyright > +; notice, this list of conditions and the following disclaimer in > +; the documentation and/or other materials provided with the > +; distribution. > +; > +; Neither the name of the author nor the names of its contributors > +; may be used to endorse or promote products derived from this > +; software without specific prior written permission. > +; > +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > +; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > +; COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, > +; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES > +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > +; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, > +; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > +; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED > +; OF THE POSSIBILITY OF SUCH DAMAGE. > + > +(declare > + (unit version) > + (uses data-structures irregex) > + (fixnum) > + (disable-interrupts)) > + > +(module chicken.version (version>=? version<?) > + > +(import scheme) > +(import (chicken base) > + (chicken irregex) > + (chicken string)) > + > +(include "common-declarations.scm") > + > +(define (version>=? v1 v2) > + (define (version->list v) > + (map (lambda (x) (or (string->number x) x)) > + (irregex-split "[-\\._]" (->string v)))) > + (let loop ((p1 (version->list v1)) > + (p2 (version->list v2))) > + (cond ((null? p1) (null? p2)) > + ((null? p2)) > + ((number? (car p1)) > + (and (number? (car p2)) > + (or (> (car p1) (car p2)) > + (and (= (car p1) (car p2)) > + (loop (cdr p1) (cdr p2)))))) > + ((number? (car p2))) > + ((string>? (car p1) (car p2))) > + (else > + (and (string=? (car p1) (car p2)) > + (loop (cdr p1) (cdr p2))))))) > + > +(define version<? (complement version>=?)) > + > +) ;; end module > -- > 2.47.3 >
