53 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			53 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
(defpackage :my-structures
 | 
						|
  (:use :cl)
 | 
						|
  (:export #:mydefstruct))
 | 
						|
 | 
						|
(in-package :my-structures)
 | 
						|
 | 
						|
(defun constructor-name (sym)
 | 
						|
  (intern (concatenate 'string "MAKE-" (string sym))))
 | 
						|
 | 
						|
(defun accessor-name (name sym)
 | 
						|
  (intern (concatenate 'string (string name) "-" (string sym))))
 | 
						|
 | 
						|
(defun setter-name (name sym)
 | 
						|
  (intern (concatenate 'string "SET-" (string name) "-" (string sym))))
 | 
						|
 | 
						|
(defun obj-type (obj)
 | 
						|
  (car obj))
 | 
						|
 | 
						|
(defun make-error-message (real expected)
 | 
						|
  (format nil "Accessor called on wrong type! Expected ~a but found ~a"
 | 
						|
	  expected real))
 | 
						|
 | 
						|
 | 
						|
(defun constructor (name slots)
 | 
						|
  `(defun ,(constructor-name name) ,slots
 | 
						|
     (list ',name ,@slots)))
 | 
						|
(defun accessors (name slots)
 | 
						|
  (loop for slot in slots
 | 
						|
	for i upfrom 1 collect
 | 
						|
	`(defun ,(accessor-name name slot) (obj)
 | 
						|
	   (if (eql (obj-type obj) ',name)
 | 
						|
	       (nth ,i obj)
 | 
						|
	       (error (make-error-message (obj-type obj) ',name))))))
 | 
						|
(defun setters (name slots)
 | 
						|
  (loop for slot in slots
 | 
						|
	for i upfrom 1 collect
 | 
						|
	`(defun ,(setter-name name slot) (obj val)
 | 
						|
	   (if (eql (obj-type obj) ',name)
 | 
						|
	       (setf (nth ,i obj) val)
 | 
						|
	       (error (make-error-message (obj-type obj) ',name))))))
 | 
						|
(defun setfers (name slots)
 | 
						|
  (loop for slot in slots collect
 | 
						|
	`(defsetf ,(accessor-name name slot)
 | 
						|
	     ,(setter-name name slot))))
 | 
						|
 | 
						|
 | 
						|
(defmacro mydefstruct (name &rest slots)
 | 
						|
  `(progn
 | 
						|
     ,(constructor name slots)
 | 
						|
     ,@ (accessors name slots)
 | 
						|
     ,@ (setters name slots)
 | 
						|
     ,@ (setfers name slots)))
 |