All pastes #1191557 Raw Edit

MOP-less custom constructor+acce

public text v1 · immutable
#1191557 ·published 2008-09-02 14:59 UTC
rendered paste body
;;;; Fun with macros and custom accessors in Common Lisp
;;;; These do not use the Meta-Object Protocol.


(declaim
 (optimize (speed 3) (safety 1)))


(defun db-defstruct-filter-key (lst)
  (let ((res nil))
    (do ((e lst (nthcdr 2 e)))
	((or (null (first e)) (null (second e))) t)
      (let ((key (first e)) (val (second e)))
	(if (not (eq key ':%id))
	    (progn
	      (push val res)
	      (push key res)))))
    res))


(defmacro db-defstruct-p (structure)
  (let ((newp (intern (format nil "DB-~S-P" structure)))
	(oldp (intern (format nil "~S-P" structure))))
    `(progn
       (declaim (inline ,newp))
       (defun ,newp (o)
	 (,oldp o)))))

(defmacro db-defstruct-constructor (structure)
  (let ((newconstructor (intern (format nil "DB-MAKE-~S" structure)))
	(oldconstructor (intern (format nil "MAKE-~S" structure))))
    `(progn
       (defun ,newconstructor (&rest parameters)
	 (let* ((valid (db-defstruct-filter-key parameters))
		(instance (apply #',oldconstructor valid)))
	   (db-constructor ',structure instance valid)
	   instance)))))

(defmacro db-defstruct-accessor (structure slot)
  (let ((newslot (intern (format nil "DB-~S-~S" structure slot)))
	(oldslot (intern (format nil "~S-~S" structure slot))))
    `(progn
       (defun ,newslot (o)
	 (,oldslot o))
       (defun (setf ,newslot) (v o)
	 (let ((res (db-fset ',structure ',slot o (,oldslot o) v)))
	   (setf (,oldslot o) res)
	   res)))))

(defmacro db-defstruct (structure &rest slots)
  (let* ((validslots
	  (remove-if #'(lambda (e) (eq (first e) '%id)) slots))
	 (accessors
	  (mapcar #'(lambda (e)
		      `(db-defstruct-accessor ,structure ,(first e)))
		  validslots)))
    `(progn
       (defstruct ,structure
	 (%id nil)
	 ,@validslots)
       (db-defstruct-constructor ,structure)
       (db-defstruct-p ,structure)
       ,@accessors
       (db-defstruct-function ',structure ',slots))))


(defun db-defstruct-function (structure &rest slots)
  (format t "; Creating structure of type ~S with slots ~S~%"
	  structure slots)
  t)

(defun db-constructor (structure object &rest parameters)
  (declare (ignore parameters))
  (format t "; Constructing object of type ~S: ~S~%" structure object))

(defun db-fset (structure slot object oldvalue value)
  (declare (ignore object))
  (format t "; Assigning ~S over ~S for slot ~S of type ~S~%"
	  value oldvalue slot structure)
  value)