(in-package "CL-USER") ;; ;; processing of defstructs ;; refers to comp-1.lisp ;; ;; ;; ;; clear hashes (defun clear-struct-tables () (setf *struct-accessor-expanders* nil) (setf *struct-size-table* nil) (setf *struct-fields-table* nil) (setf *struct-fields-inits-table* nil)) (clear-struct-tables) ;; struct accessor hash (defun is-struct-accessor (head) (assoc head *struct-accessor-expanders*)) (defun get-struct-accessor-val (head) (cdr (assoc head *struct-accessor-expanders*))) (defun rewrite-struct-accessor (e) (expand `(%svref ,(cadr e) ,(cdr (assoc (car e) *struct-accessor-expanders*))))) (defun enter-accessor (sym offset) (push (cons sym offset) *struct-accessor-expanders*)) ;; struct size hash (defun get-struct-size (strct) (let ((r (assoc strct *struct-info-table*))) (if r (cdr r) nil))) ;; struct fields hash (defun get-struct-fields (strct) (let ((r (assoc strct *struct-fields-table*))) (if r (cdr r) nil))) (defun set-struct-fields (strct field-list) (push (cons strct field-list) *struct-fields-table*)) ;; struct fields-inits hash (defun get-struct-fields-inits (strct) (let ((r (assoc strct *struct-fields-inits-table*))) (if r (cdr r) nil))) (defun set-struct-fields-inits (strct field-list) (push (cons strct field-list) *struct-fields-inits-table*)) (defun defstruct-expand (e) (let ((init-info (cadr e)) (fields (cddr e))) (let ((struct-name (if (listp init-info) (car init-info) init-info))) (let ((offset 1) (incl nil) (conc-name (concatenate 'string (symbol-name struct-name) "-")) (predicate (intern (concatenate 'string (symbol-name struct-name) "-p")))) (if (listp init-info) (do ((l (cdr init-info) (cdr l))) ((null l)) (format t "l = ~a~%" l) (case (car (car l)) ((:include) (setf incl (cadr (car l)))) ((:conc-name) (setf conc-name (if (cadr (car l)) (symbol-name (cadr (car l))) ""))) ((:predicate) (setf predicate (cadr (car l))))))) (format t "incl = ~a~%" incl) (when incl (do ((p (get-struct-fields incl) (cdr p)) (i offset (+ i 1))) ((null p)) (enter-accessor (intern (concatenate 'string conc-name (symbol-name (car p)))) i) (setf offset (+ offset 1)))) (when (stringp (car fields)) (setf fields (cdr fields))) (let ((own-fields-names (mapcar #'(lambda (z) (if (symbolp z) z (car z))) fields)) (fields-inits (mapcar #'(lambda (z) (if (listp z) (cadr z) nil)) fields))) (format t "sftab = ~a~%" *struct-fields-table*) (format t "*** incl = ~a ~% fields = ~a~%" (get-struct-fields incl)) (set-struct-fields struct-name (append (get-struct-fields incl) own-fields-names)) (setf fields-inits (append (get-struct-fields-inits incl) fields-inits)) (set-struct-fields-inits struct-name fields-inits) (do ((p own-fields-names (cdr p))) ((null p)) (enter-accessor (intern (concatenate 'string conc-name (symbol-name (car p)))) offset) (setf offset (+ offset 1))) (let* ((make-name (intern (concatenate 'string "MAKE-" (symbol-name struct-name)))) (res `(progn (defun ,make-name () (%print ,offset) (let ((v (%make-vector ,offset))) ,@(do ((i 1 (+ i 1)) (res nil res)) ((>= i offset) (reverse res)) (push `(%set-svref v ,i ,(nth (- i 1) fields-inits)) res)) v))))) res)))))) (defun setf-expand (e) (let* ((assign-list (cdr e)) (res (do ((p assign-list (cddr p)) (res nil)) ((null p)(reverse res)) (push (setf-1-expand (car p) (cadr p)) res)))) (if (length=1 res) (car res) (cons 'progn res)))) (defun setf-1-expand (lval val) (if (symbolp lval) `(setq ,lval ,val) (if (listp lval) (let ((head (car lval)) (obj (cadr lval))) (if (eq head 'char) (expand `(set-char ,(cadr lval) ,(caddr lval) ,val)) (if (is-struct-accessor head) (expand `(%set-svref ,obj ,(get-struct-accessor-val head) ,val)) (error "setf-1-expand: 000: no struct accessor found")))) (error "setf-1-expand: 001: case not implemented")))) (setf *s1* '(defstruct pt x y z)) (setf *s2* '(defstruct (pt2 (:include pt)) u (v 23) w)) (print (defstruct-expand *s1*)) (print (defstruct-expand *s2*)) (print *struct-fields-table*) (print *struct-accessor-expanders*) (print (setf-expand '(setf (pt2-x obj1) 12))) (print (rewrite-struct-accessor '(pt2-u obj)))