[armedbear-devel] Problem with defstruct accessor functions and included structures in combination with conc-names
Ralf Moeller
moeller at tu-harburg.de
Fri Aug 3 13:01:10 UTC 2012
The following file causes a problem in ABCL (1.1.0-dev-svn-14041) when compiled (!) and loaded.
(in-package cl-user)
(defstruct a (s1 nil))
(defstruct (b (:include a) (:conc-name foo-)) (s2 nil))
(defstruct (c (:include a) (:conc-name foo-)) (s3 nil))
(defun test ()
(let ((x (make-b :s1 1 :s2 2)))
(foo-s1 x)))
CL-USER(4): (test)
#<THREAD "interpreter" {2EF7D41F}>: Debugger invoked on condition of type SIMPLE-TYPE-ERROR
The value #<B {564434F7}> is not of type C.
Restarts:
0: TOP-LEVEL Return to top level.
[1] CL-USER(6): (lisp-implementation-version)
"1.1.0-dev-svn-14041"
[1] CL-USER(7):
The problem is that the defstruct declaration for c "overwrites" the accessor foo-s1 generated by defstruct b.
If foo-s1 is called for a b instance, the type assertions introduced by define-reader (and define-writer, see the
ABCL implementation for defstruct) cause the error described above.
The code above runs fine in ACL, Lispworks, SBCL, and other Lisps.
I had to remove the generation of type assertions in define-reader and define-accessor (see below)
to make the code work in ABCL. Note, however, that there is no type checking pursued with the code below.
Thus, a better solution might be developed.
Regards,
Ralf Moeler
http://www.sts.tu-harburg.de/~r.f.moeller/
(defun define-reader (slot)
(let ((accessor-name (dsd-reader slot))
(index (dsd-index slot))
(type (dsd-type slot)))
(cond ((eq *dd-type* 'list)
`((declaim (ftype (function * ,type) ,accessor-name))
(setf (symbol-function ',accessor-name)
(make-list-reader ,index))))
((or (eq *dd-type* 'vector)
(and (consp *dd-type*) (eq (car *dd-type*) 'vector)))
`((declaim (ftype (function * ,type) ,accessor-name))
(setf (symbol-function ',accessor-name)
(make-vector-reader ,index))
(define-source-transform ,accessor-name (instance)
`(aref ,instance ,,index))))
(t
`((declaim (ftype (function * ,type) ,accessor-name))
(setf (symbol-function ',accessor-name)
(make-structure-reader ,index ',*dd-name*))
(define-source-transform ,accessor-name (instance)
,(if (eq type 't)
``(structure-ref ,instance ,,index)
``(the ,',type
(structure-ref ,instance ,,index)))))))))
(defun define-writer (slot)
(let ((accessor-name (dsd-reader slot))
(index (dsd-index slot)))
(cond ((eq *dd-type* 'list)
`((setf (get ',accessor-name 'setf-function)
(make-list-writer ,index))))
((or (eq *dd-type* 'vector)
(and (consp *dd-type*) (eq (car *dd-type*) 'vector)))
`((setf (get ',accessor-name 'setf-function)
(make-vector-writer ,index))
(define-source-transform (setf ,accessor-name) (value instance)
`(aset ,instance ,,index ,value))))
(t
`((setf (get ',accessor-name 'setf-function)
(make-structure-writer ,index ',*dd-name*))
(define-source-transform (setf ,accessor-name) (value instance)
`(structure-set ,instance ,,index ,value)))))))
More information about the armedbear-devel
mailing list