Menu

#281 Lexical Binding in Toplevel PROGN (Clisp 2.35)

closed-duplicate
clisp (524)
5
2005-10-30
2005-10-29
stranger
No

As an example of the bug, The Common Lisp Zip Library
project (http://common-lisp.net/project/zip/ ) contains
the following in zip.lisp:

(defmacro define-record (constructor (&key (length
(gensym))) &rest fields)
`(progn
(defconstant ,length
,(loop
for (nil type) in fields
sum (ecase type (:int 4) (:short 2))))
(defun ,constructor (&optional s)
; BAD: ,length expands to #Gxxxx, instead of the
actual value.
; The CLISP 2.35 compiler doesn't complain, but the
loader chokes on the
; uninterned symbol.
(let ((bytes (make-byte-array ,length)))
(when s
(read-sequence bytes s))
bytes))
,@(loop
for (name type) in fields
for offset = 0 then (+ offset length)
for length = (ecase type (:int 4) (:short 2))
for reader = (ecase type (:int 'get-int) (:short
'get-short))
unless (eq name :dummy)
append `((defun ,name (r)
(,reader r ,offset))
(defun (setf ,name) (newval r)
(setf (,reader r ,offset)
newval))))))

...

(define-record make-directory-entry ()
(cd/signature :int)
(cd/version-made-by :short)
(cd/version-needed-to-extract :short)
(cd/flags :short)
(cd/method :short)
(cd/time :short)
(cd/date :short)
(cd/crc :int)
(cd/compressed-size :int)
(cd/size :int)
(cd/name-length :short)
(cd/extra-length :short)
(cd/comment-length :short)
(cd/disc-number :short)
(cd/internal-attributes :short)
(cd/external-attributes :int)
(cd/offset :int))

[7]> (pprint (macroexpand '(define-record
make-directory-entry () (end/signature :int)
(end/this-disc :short) (end/central-directory-disc
:short) ...)))

expands to the following:

(PROGN (DEFCONSTANT #:G9428 46)
(DEFUN MAKE-DIRECTORY-ENTRY (&OPTIONAL S)
(LET ((BYTES (MAKE-BYTE-ARRAY #:G9428))) (WHEN S
(READ-SEQUENCE BYTES S))
BYTES))
(DEFUN END/SIGNATURE (R) (GET-INT R 0))
(DEFUN (SETF END/SIGNATURE) (NEWVAL R) (SETF (GET-INT
R 0) NEWVAL))
(DEFUN END/THIS-DISC (R) (GET-SHORT R 4)) ...)

Whereas Clisp 2.35 compiles the file, it fails on
loading, giving the following:

...
;; Loading file /home/stranger/oss/lisp/zip/zip.fas ...
*** - EVAL: variable #:G9428 has no value
The following restarts are available:
USE-VALUE :R1 You may input a value to be
used instead of #:G9428.
STORE-VALUE :R2 You may input a new value for
#:G9428.
RETRY :R3
Retry performing #<ASDF:LOAD-OP NIL #x20446756> on
#<ZIP-SYSTEM::SILENT-SOURCE-FILE
"zip" #x20448276>.
ACCEPT :R4
Continue, treating #<ASDF:LOAD-OP NIL #x20446756> on
#<ZIP-SYSTEM::SILENT-SOURCE-FILE
"zip" #x20448276> as having been successful.
ABORT :R5 ABORT

As defined in CLHS, Common Lisp treats forms in a
toplevel PROGN as toplevel forms, and the progn creates
a lexical environment for those forms. I haven't yet
found anything in the standard that defines either
behavior as implementation dependent.

SBCL 0.9.5 loads the aforementioned compiled file
without complaint, and I believe others had success
with the zip library on other implementations. This
would lead me to believe that the macro is valid Lisp code.

Let me know if I have missed something.

Discussion

  • Sam Steingold

    Sam Steingold - 2005-10-30
    • labels: --> clisp
    • milestone: --> ANSI compliance issue
    • assigned_to: nobody --> sds
    • status: open --> closed-duplicate
     
  • Sam Steingold

    Sam Steingold - 2010-09-22

    This artifact has been marked as a duplicate of artifact 836838 with reason:
    same issue

     

Log in to post a comment.