diff --git a/scheme/ikarus.boot.orig b/scheme/ikarus.boot.orig index 5b5e09a..5f30cc9 100644 Binary files a/scheme/ikarus.boot.orig and b/scheme/ikarus.boot.orig differ diff --git a/scheme/psyntax.expander.ss b/scheme/psyntax.expander.ss index 093cad3..883c871 100644 --- a/scheme/psyntax.expander.ss +++ b/scheme/psyntax.expander.ss @@ -2759,6 +2759,64 @@ ((null? ls) '()) ((memq (car ls) (cdr ls)) (remove-dups (cdr ls))) (else (cons (car ls) (remove-dups (cdr ls)))))) + (define (parse-library-name spec) + (define (subversion? x) + (and (integer? x) (exact? x) (>= x 0))) + (define (subversion-pred x*) + (syntax-match x* () + [n (subversion? n) + (lambda (x) (= x n))] + [(p? sub* ...) (eq? p? 'and) + (let ([p* (map subversion-pred sub*)]) + (lambda (x) + (for-all (lambda (p) (p x)) p*)))] + [(p? sub* ...) (eq? p? 'or) + (let ([p* (map subversion-pred sub*)]) + (lambda (x) + (exists (lambda (p) (p x)) p*)))] + [(p? sub) (eq? p? 'not) + (let ([p (subversion-pred sub)]) + (lambda (x) + (not (p x))))] + [(p? n) (and (eq? p? '<=) (subversion? n)) + (lambda (x) (<= x n))] + [(p? n) (and (eq? p? '>=) (subversion? n)) + (lambda (x) (>= x n))] + [_ (error 'import "invalid sub-version spec" x* spec)])) + (define (version-pred x*) + (syntax-match x* () + [() (lambda (x) #t)] + [(c ver* ...) (eq? c 'and) + (let ([p* (map version-pred ver*)]) + (lambda (x) + (for-all (lambda (p) (p x)) p*)))] + [(c ver* ...) (eq? c 'or) + (let ([p* (map version-pred ver*)]) + (lambda (x) + (exists (lambda (p) (p x)) p*)))] + [(c ver) (eq? c 'not) + (let ([p (version-pred ver)]) + (lambda (x) (not (p x))))] + [(sub* ...) + (let ([p* (map subversion-pred sub*)]) + (lambda (x) + (let f ([p* p*] [x x]) + (cond + [(null? p*) #t] + [(null? x) #f] + [else + (and ((car p*) (car x)) + (f (cdr p*) (cdr x*)))]))))] + [_ (error 'import "invalid version spec" x* spec)])) + (let f ([x spec]) + (syntax-match x () + [((version-spec* ...)) + (values '() (version-pred version-spec*))] + [(x . x*) (symbol? x) + (let-values ([(name pred) (f x*)]) + (values (cons x name) pred))] + [() (values '() (lambda (x) #t))] + [_ (stx-error spec "invalid import spec")]))) (define (get-import spec) (syntax-match spec () ((rename isp (old* new*) ...) @@ -2790,15 +2848,23 @@ (symbol->string (car x)))) (cdr x))) subst))) - ((library name) (eq? library 'library) + ((library (spec* ...)) (eq? library 'library) ;;; FIXME: versioning stuff - (let ((lib (find-library-by-name name))) - (unless lib - (error 'import - "cannot find library satisfying required name" - name)) - (imp-collector lib) - (library-subst lib))) + (let-values ([(name pred) (parse-library-name spec*)]) + (when (null? name) + (error 'import "empty library name" spec*)) + (let ((lib (find-library-by-name name))) + (unless lib + (error 'import + "cannot find library with required name" + name)) + (unless (pred (library-version lib)) + (error 'import + "library does not satisfy version specification" + lib + spec*)) + (imp-collector lib) + (library-subst lib)))) ((x x* ...) (not (memq x '(rename except only prefix library))) (get-import `(library (,x . ,x*)))) diff --git a/scheme/psyntax.library-manager.ss b/scheme/psyntax.library-manager.ss index acb0440..6775ecd 100644 --- a/scheme/psyntax.library-manager.ss +++ b/scheme/psyntax.library-manager.ss @@ -20,9 +20,10 @@ (library (psyntax library-manager) (export imported-label->binding library-subst installed-libraries - visit-library library-name library-exists? find-library-by-name - install-library library-spec invoke-library extend-library-subst! - extend-library-env! current-library-expander current-library-collection) + visit-library library-name library-version library-exists? + find-library-by-name install-library library-spec invoke-library + extend-library-subst! extend-library-env! current-library-expander + current-library-collection) (import (rnrs) (psyntax compat) (rnrs r5rs)) (define (make-collection) @@ -47,15 +48,15 @@ x))) (define-record library - (id name ver imp* vis* inv* subst env visit-state invoke-state visible?) + (id name version imp* vis* inv* subst env visit-state invoke-state visible?) (lambda (x p) (unless (library? x) (error 'record-type-printer "not a library")) (display (format "#" - (if (null? (library-ver x)) + (if (null? (library-version x)) (library-name x) - (append (library-name x) (list (library-ver x))))) + (append (library-name x) (list (library-version x))))) p))) (define (find-dependencies ls) @@ -274,6 +275,6 @@ (lambda (x) (unless (library? x) (error 'library-spec "not a library" x)) - (list (library-id x) (library-name x) (library-ver x)))) + (list (library-id x) (library-name x) (library-version x)))) )