git.fiddlerwoaroof.com
Raw Blame History
(in-package #:fwoar.lisputils)

(defmacro with-accessors* ((&rest accessors) object &body body)
  `(with-accessors ,(ensure-mapping accessors) ,object
     ,@body))

(defmacro new (class &rest initializer-syms)
  (multiple-value-bind (required optional rest) (parse-ordinary-lambda-list initializer-syms)
    (when optional
      (error "new doesn't handle optional arguments"))
    (if rest
        `(make-instance ,class
                        ,@(mapcan (lambda (_1)
                                    (list (alexandria:make-keyword _1)
                                          _1))
                                  required)
                        ,(make-keyword rest) ,rest)
        `(make-instance ,class
                        ,@(mapcan (lambda (_1)
                                    (list (alexandria:make-keyword _1)
                                          _1))
                                  initializer-syms)))))

(defmacro defclass+ (name (&rest super) &body (direct-slots &rest options))
  (let ((initargs (append (mapcan (lambda (class)
                                    (typecase class
                                      (cons (cadr class))
                                      (t nil)))
                                  super)
                          (mapcan (lambda (slot)
                                    (alexandria:ensure-list
                                     (alexandria:when-let ((initarg (getf (cdr slot)
                                                                          :initarg)))
                                       (make-symbol (symbol-name initarg)))))
                                  direct-slots))))
    `(progn (defclass ,name
                ,(mapcar (lambda (it)
                           (typecase it
                             (cons (car it))
                             (t it)))
                  super)
              ,direct-slots
              ,@options)
            (defun ,name (,@initargs)
              (fw.lu:new ',name ,@initargs)))))

(defun-ct %constructor-name (class)
  (format nil "~a-~a" '#:make class))

(defmacro make-constructor (class &rest args)
  (destructuring-bind (class &optional (constructor-name (intern (%constructor-name class))))
      (ensure-list class)
    `(defgeneric ,constructor-name (,@args)
       (:method (,@args)
         (new ',class ,@args)))))