[Openmcl-devel] with-package

Taoufik Dachraoui dachraoui.taoufik at gmail.com
Sun Jan 13 11:24:53 PST 2013


hi

the previous version of mb contains a lot of errors (sorry)

I found the solution to the issue encountered in with-package, I do not use
any hacking around
the lisp reader, the solution is simple and safe (i hope)

Here is an explanation of the issue and the solution:

? (with-package (calculus) (share 3))

1. at read time the symbol SHARE is created by the reader
2. at execution time the use of calculus will unintern SHARE and create a
new one; this was the problem,
when I unintern the symbol, the symbol created by the reader will have no
package (symbol-package is nil)

The solution is to not unintern symbols, instead I use a function
%set-symbol as follows:

(defun %set-symbol (s1 s2)
  (setf (symbol-plist s1) (symbol-plist s2))
  (if (boundp s2)
      (setf (symbol-value s1) (symbol-value s2))
      (makunbound s1))
  (if (fboundp s2)
      (if (null (macro-function s2))
          (setf (symbol-function s1) (symbol-function s2))
          (setf (macro-function s1) (macro-function s2)))
      (fmakunbound s1)))

Check the function %import to see when %set-symbol is called.

This way the imported symbol from calculus will bound/fbound the symbol
created by the reader

Kind regards
Taoufik


(defpackage "MB" (:export "USE" "UNUSE" "WITH-PACKAGE" "%SET-SYMBOL"))
(in-package "MB")

(defun %new-symbol (s package &optional v)
  (setf (symbol-value (intern s package)) v))

(defun %symbol-value (s &optional package)
  (let ((r
 (if (null package)
     (symbol-value (find-symbol s))
     (symbol-value (find-symbol s package)))))
    (format t "%symbol-vale ~S = ~S~%" s r) r))

(defun (setf %symbol-value) (v s &optional package)
  (if (null package)
      (setf (symbol-value (find-symbol s)) v)
      (setf (symbol-value (find-symbol s package)) v)))

(defun %set-symbol (s1 s2)
  (setf (symbol-plist s1) (symbol-plist s2))
  (if (boundp s2)
      (setf (symbol-value s1) (symbol-value s2))
      (makunbound s1))
  (if (fboundp s2)
      (if (null (macro-function s2))
  (setf (symbol-function s1) (symbol-function s2))
  (setf (macro-function s1) (macro-function s2)))
      (fmakunbound s1)))

(defun %import (s)
  (let ((ss (find-symbol (symbol-name s))))
    (if (not (null ss))
        (progn
          (push
           (if (eq (symbol-package ss) *package*)
               (copy-symbol ss t)
               (cons (symbol-name ss) (symbol-package ss)))
           (gethash (symbol-name s) (%symbol-value
"**MB-HASH-HIDDEN-SYMBOLS**")))
          (%set-symbol ss s)) ;; do not unintern/import; it creates an
issue when using with-package
(import s))))

(defun %unimport (s)
  (let ((asym (pop (gethash (symbol-name s)
    (%symbol-value "**MB-HASH-HIDDEN-SYMBOLS**")))))
    (if (not (null asym))
(if (consp asym)
    (%import (find-symbol (car asym) (cdr asym)))
    (let ((sym (intern (symbol-name s))))
      (%set-symbol sym asym)))
(unintern (find-symbol (symbol-name s))))
    (if (null (gethash (symbol-name s)
       (%symbol-value "**MB-HASH-HIDDEN-SYMBOLS**")))
(remhash (symbol-name s)
 (%symbol-value "**MB-HASH-HIDDEN-SYMBOLS**")))))

(defun %make-package (file nickname)
  (if (null (file-write-date file))
      (error (format nil "file not found (~S)" file))
      (let ((*package*
     (if (null (find-package nickname))
 (make-package file
       :use '("CCL" "COMMON-LISP" "MB")
       :nicknames `(,nickname))
 (find-package nickname))))
(%new-symbol "**MB-PACKAGE-TIMESTAMP**" *package* (file-write-date file))
(%new-symbol "**MB-HASH-HIDDEN-SYMBOLS**" *package* (make-hash-table :test
'equal))
(load file))))

(defun %use (name)
  (if (and (not (eq (find-package name) *package*))
   (or (null (%symbol-value "**MB-USED-PACKAGES**"))
       (not (eq (find-package name) (car (%symbol-value
"**MB-USED-PACKAGES**"))))))
      (progn
(if (null (find-package name))
    (%make-package (format nil "~A/~A.LISP" (ccl::current-directory-name)
(string name)) name)
    (if (and (not (null (find-symbol "**MB-PACKAGE-TIMESTAMP**"
(find-package name))))
     (> (file-write-date (package-name (find-package name)))
(%symbol-value "**MB-PACKAGE-TIMESTAMP**" (find-package name))))
(%make-package (package-name (find-package name)) name)))
(if (null (find-symbol "**MB-HASH-HIDDEN-SYMBOLS**" (symbol-package name)))
    (%new-symbol "**MB-HASH-HIDDEN-SYMBOLS**" *package* (make-hash-table)))
(do-external-symbols (s (find-package name)) (%import s))
(push (find-package name) (%symbol-value "**MB-USED-PACKAGES**")))))


(defun %unuse (name)
"only unuse the last used package"
  (if (not (null (find-package name)))
      (if (eq (find-package name) (car (%symbol-value
"**MB-USED-PACKAGES**")))
  (let ((pkg (pop (%symbol-value "**MB-USED-PACKAGES**"))))
    (do-external-symbols (s pkg) (%unimport s))
    (if (not (null (find-symbol "**MB-PACKAGE-TIMESTAMP**" pkg)))
(delete-package pkg)))
  (error "cannot unuse package ~S~%" (find-package name)))))

(defmacro use (&rest names)
  `(progn
     (if (null (find-symbol "**MB-USED-PACKAGES**")) (%new-symbol
"**MB-USED-PACKAGES**" *package*))
     (dolist (name ',names) (%use name))))

(defmacro unuse (&rest names)
  (if (null names)
      `(%unuse (car (%symbol-value "**MB-USED-PACKAGES**")))
      `(dolist (name ',names) (%unuse name))))

(defmacro with-package ((&rest names) &body body)
  (let ((r (gensym)) (e (gensym)))
    `(progn
       (use , at names)
       (multiple-value-bind (,r ,e)
           (ignore-errors
             (multiple-value-list (progn , at body)))
         (unuse ,@(reverse names))
         (if (null ,e)
             (values-list ,r)
             (error (format nil "~S" ,e)))))))






On Sun, Jan 13, 2013 at 10:39 AM, Pascal J. Bourguignon <
pjb at informatimago.com> wrote:

> Taoufik Dachraoui <dachraoui.taoufik at gmail.com> writes:
>
> > replace with-package by the following:
>
> 1- can't access lexical bindings:
>
> cl-user> (let ((hello 'world))
>            (mb:with-package (MB)
>              (print hello)))
>
> ;Compiler warnings :
> ;   In an anonymous lambda form: Unused lexical variable hello
> > Debug: #<unbound-variable #x302001E4CDBD>
>
>
> 2- the error messages are not printed nicely (after "Debug: ").
>    Compare with:
>
> cl-user> (let ((hello 'world))
>            (print whatchamacalit))
> ;Compiler warnings :
> ;   In an anonymous lambda form: Undeclared free variable whatchamacalit
> ;   In an anonymous lambda form: Unused lexical variable hello
> > Debug: Unbound variable: whatchamacalit
>
>
> --
> __Pascal Bourguignon__                     http://www.informatimago.com/
> A bad day in () is better than a good day in {}.
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20130113/a2000421/attachment.htm>


More information about the Openmcl-devel mailing list