cl-scopes/shape/shape.lisp

83 lines
2.8 KiB
Common Lisp

;;;; cl-scopes/shape - really abstract basic data shape definitions.
(defpackage :scopes/shape
(:use :common-lisp)
(:local-nicknames (:util :scopes/util)
(:mop :closer-mop))
(:export #:factory #:create #:create-item #:record-factory
#:record #:print-fields #:print-slots
#:head-fields #:head #:head-value #:head-plist
#:data-fields #:data #:data-value))
(in-package :scopes/shape)
;;;; abstract base item and factory
(defclass factory ()
((item-class :reader item-class :initarg :item-class)))
(defclass item ()
((factory :reader factory :initarg :factory :allocation :class)))
(defun create (cls &rest args)
(let* ((ic (find-class cls)))
(mop:ensure-finalized ic)
(apply #'make-instance cls :factory (factory (mop:class-prototype ic)) args)))
(defun create-item (fac &rest args)
(apply #'make-instance (item-class fac) args))
;;;; record class, factory, utilities
(defclass record-factory (factory)
((item-class :initform 'record)
(head-fields :reader head-fields :initarg :head-fields
:initform '(:taskid :username))
(data-fields :reader data-fields :initarg :data-fields :initform nil)))
(defclass record (item)
((factory :initform (make-instance 'record-factory))
(head-fields :reader head-fields :initarg :head-fields
:initform '(:taskid :username) :allocation :class)
(data-fields :reader data-fields :initarg :data-fields
:initform nil :allocation :class)
(head :reader head :initarg :head)
(data :accessor data :initarg :data :initform nil)))
(defmethod initialize-instance :after ((rec record) &key head &allow-other-keys)
(setf (slot-value rec 'head) (util:rfill (head-fields rec) head)))
(defmethod print-object ((rec record) stream)
(print-fields rec stream 'head 'data))
(defun head-value (rec key)
(elt (head rec) (position key (head-fields rec))))
(defun (setf head-value) (val rec key)
(setf (elt (head rec) (position key (head-fields rec))) val))
(defun head-plist (rec)
(let (pl (hv (head rec)))
(dolist (hf (head-fields rec))
(setf pl (cons hf (cons (util:from-keyword (pop hv)) pl))))
pl))
(defun data-value (rec key)
(getf (data rec) key))
(defun (setf data-value) (val rec key)
(setf (getf (data rec) key) val))
;;;; printing utilities
(defun print-fields (rec stream &rest fields)
(let ((fm (util:make-vars-format fields)))
(print-unreadable-object (rec stream :type t)
(apply #'format stream fm (mapcar #'(lambda (x) (funcall x rec)) fields)))))
(defun print-slots (rec stream &rest fields)
(let ((fm (util:make-vars-format fields)))
(print-unreadable-object (rec stream :type t)
(apply #'format stream fm
(mapcar #'(lambda (x) (when (slot-boundp rec x) (slot-value rec x)))
fields)))))