Pascal Bourguignon <[EMAIL PROTECTED]> writes:

> We'd still have to resolve the version problem first.

Easy. (Feel free to utilize, mangle, and ignore -- as suits
the project.)

;;;; Sketch for versioned packages, "basically works", but most
;;;; certainly not well tested. Ironically, notice the lack of
;;;; both documentation and specification...
;;;;
;;;; Placed in Public Domain by the author.

(defvar *package-versions* (make-hash-table :test #'equal))
(defvar *versioned-packages* (make-hash-table))

(defun package-version (package)
  (cdr (gethash (find-package package) *versioned-packages*)))

(defun package-basename (package)
  (car (gethash (find-package package) *versioned-packages*)))

(defun find-package-version (package version)  
  (car (rassoc version (gethash (package-basename package) 
*package-versions*))))

(defun list-package-versions (package)
  (sort (mapcar #'cdr (gethash (package-basename package) *package-versions*))
        #'<))

(defun steal-package-nickname (package nickname)
  (let ((old (find-package nickname)))
    (when old
      (when (equal nickname (package-name old))
        (error "Cannot steal the primary name of a package: ~A" old))
      (rename-package old (package-name old) 
                      (remove nickname (package-nicknames old) :test #'equal))))
  (rename-package package (package-name package)
                  (cons nickname (package-nicknames package))))

(defmacro defpackage* (name &body options)
  (let* ((version (second (assoc :version options)))
         (rest (remove :version options :key #'car))
         (sname (string name))
         (vname (format nil "~A.~D" name version)))
    (check-type version (or null real))
    `(progn
       (defpackage ,vname ,@rest)
       ,@
       (when version
         (when (< 1 (count :version options :key #'car))
           (error "Multiple :VERSION options in DEFPACKAGE* ~A" name))
         `((let ((this (find-package ,vname))
                 (old (find-package ,sname)))
             (setf (gethash this *versioned-packages*) (cons ,sname ,version))
             (pushnew (cons this ,version) (gethash ,sname *package-versions*)
                      :key #'cdr)
             (when (or (not old) (< (package-version old) ,version))
               (steal-package-nickname this ,sname))))))))

(defpackage* foo (:version 1))
(defpackage* foo (:version 2))

(package-version (find-package "FOO"))         ; => 2 
(list-package-versions (find-package "FOO.1")) ; => (1 2)
(package-basename (find-package "FOO.1"))      ; => "FOO"
(find-package-version (find-package "FOO") 1)  ; => #<PACKAGE "FOO.1">

Cheers,

  -- Nikodemus              Schemer: "Buddha is small, clean, and serious."
                   Lispnik: "Buddha is big, has hairy armpits, and laughs."

_______________________________________________
Gardeners mailing list
[email protected]
http://www.lispniks.com/mailman/listinfo/gardeners

Reply via email to