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
> 


Reply via email to