Advertisement
Guest User

Another N hours wasted... :|

a guest
Dec 5th, 2018
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 8.84 KB | None | 0 0
  1. (in-package #:k.binary.structures)
  2.  
  3. (defclass %slot ()
  4.   ((accessor :initarg :accessor
  5.              :reader %accessor-of
  6.              :type symbol)
  7.    (count :initarg :count
  8.           :reader %count-of
  9.           :type (integer 1))
  10.    (name :initarg :name
  11.          :reader %name-of
  12.          :type symbol)
  13.    (offset :initarg :offset
  14.            :reader %offset-of
  15.            :type (integer 0))
  16.    (type :initarg :type
  17.          :reader %type-of
  18.          :type %type)))
  19.  
  20. (defclass %structure (%type)
  21.   ((constructor :initarg :constructor
  22.                 :reader %constructor-of
  23.                 :type symbol)
  24.    (offset :initarg :offset
  25.            :reader %offset-of
  26.            :type (integer 0))
  27.    (slots :initarg :slots
  28.           :reader %slots-of
  29.           :type list)
  30.    (superstructure :initarg :superstructure
  31.                    :reader %superstructure-of
  32.                    :type (or null %structure))))
  33.  
  34. (defstruct (binary-structure
  35.             (:constructor %make-binary-structure))
  36.   "The superstructure of all binary structures.")
  37.  
  38. (setf (%symbol-type 'binary-structure)
  39.       (make-instance '%structure
  40.                      :constructor '%make-binary-structure
  41.                      :name 'binary-structure
  42.                      :offset 0
  43.                      :size 0
  44.                      :slots nil
  45.                      :superstructure nil))
  46.  
  47. (defmethod %read-from (offset (type %structure) vector)
  48.   (let ((instance (funcall (%constructor-of type))))
  49.     (%read-slots-from instance offset vector)
  50.     instance))
  51.  
  52. (defgeneric %read-slots-from (instance offset vector)
  53.   (:method-combination progn :most-specific-last))
  54.  
  55. (defmethod %size-of ((instance %slot))
  56.   (* (%count-of instance)
  57.      (%size-of (%type-of instance))))
  58.  
  59. (defun %structure-p (object)
  60.   (typep object '%structure))
  61.  
  62. (defmethod %write-into (offset (type %structure) value vector)
  63.   (%write-slots-into value offset vector))
  64.  
  65. (defgeneric %write-slots-into (instance offset vector)
  66.   (:method-combination progn :most-specific-last))
  67.  
  68. (defun canonicalize-superstructure (superstructure-name)
  69.   (let ((superstructure-name
  70.          (or superstructure-name 'binary-structure)))
  71.     (check-type superstructure-name symbol)
  72.     (assert (subtypep superstructure-name 'binary-structure))
  73.     (%symbol-type superstructure-name)))
  74.  
  75. (defun make-array-initform (count initform type)
  76.   `(make-array ,count
  77.                :element-type ',(%name-of type)
  78.                ,@(if (%primitive-p type)
  79.                      `(:initial-element ,initform)
  80.                      `(:initial-contents
  81.                        `#(,,@(loop for i below count
  82.                                    collect initform))))))
  83.  
  84. (defun make-defstruct-form (structure)
  85.   (let ((name (%name-of structure)))
  86.     `(defstruct (,name
  87.                  (:conc-name ,(symbolicate '% name '-))
  88.                  (:constructor ,(%constructor-of structure))
  89.                  (:include ,(%name-of (%superstructure-of structure))))
  90.        ,@(mapcar #'make-defstruct-slot-description
  91.                  (%slots-of structure)))))
  92.  
  93. (defun make-defstruct-slot-initform (count type)
  94.   (let ((initform (%initform-for type)))
  95.     (if (> count 1)
  96.         (make-array-initform count initform type)
  97.         initform)))
  98.  
  99. (defun make-defstruct-slot-description (slot)
  100.   (let ((count (%count-of slot))
  101.         (type (%type-of slot)))
  102.     `(,(%name-of slot)
  103.       ,(make-defstruct-slot-initform count type)
  104.       :type
  105.       ,(make-defstruct-slot-type count type))))
  106.  
  107. (defun make-defstruct-slot-type (count type)
  108.   (let ((type-name (%name-of type)))
  109.     (if (> count 1)
  110.         `(array ,type-name (,count))
  111.         type-name)))
  112.  
  113. (defun make-read-form (accessor count start type vector)
  114.   (cond ((> count 1)
  115.          (with-gensyms (index offset storage)
  116.            `(loop with ,storage = ,accessor
  117.                   for ,index from 0 below ,count
  118.                   for ,offset from ,start by ,(%size-of type)
  119.                   do ,(make-read-form `(aref ,storage ,index)
  120.                                       1
  121.                                       offset
  122.                                       type
  123.                                       vector))))
  124.          ((%structure-p type)
  125.           `(%read-slots-from ,accessor ,start ,vector))
  126.          (t `(setf ,accessor
  127.                    (read-from ',(%name-of type) ,vector ,start)))))
  128.  
  129. (defun make-slot-accessor-call (place structure slot)
  130.   (let ((accessor-name
  131.          (symbolicate '%
  132.                       (%name-of structure)
  133.                       '-
  134.                       (%name-of slot))))
  135.     `(,accessor-name ,place)))
  136.  
  137. (defun make-slot-reader-method (structure slot)
  138.   (with-gensyms (index instance)
  139.     (if (> (%count-of slot) 1)
  140.         `(defmethod ,(%accessor-of slot)
  141.              ((,instance ,(%name-of structure)) ,index)
  142.            (check-type ,index array-index)
  143.            (aref ,(make-slot-accessor-call instance structure slot)
  144.                  ,index))
  145.         `(defmethod ,(%accessor-of slot)
  146.              ((,instance ,(%name-of structure)))
  147.            ,(make-slot-accessor-call instance structure slot)))))
  148.  
  149. (defun make-structure-reader-method (structure)
  150.   (with-gensyms (instance offset vector)
  151.     `(defmethod %read-slots-from
  152.          ((,instance ,(%name-of structure)) ,offset ,vector)
  153.        ,@(loop for slot in (%slots-of structure)
  154.                collect (make-read-form
  155.                         (make-slot-accessor-call instance structure slot)
  156.                         (%count-of slot)
  157.                         `(+ ,offset ,(%offset-of slot))
  158.                         (%type-of slot)
  159.                         vector)))))
  160.  
  161. (defun make-slot-writer-method (structure slot)
  162.   (with-gensyms (index instance value)
  163.     (if (> (%count-of slot) 1)
  164.         `(defmethod (setf ,(%accessor-of slot))
  165.              (,value (,instance ,(%name-of structure)) ,index)
  166.            (check-type ,value ,(%name-of (%type-of slot)))
  167.            (check-type ,index array-index)
  168.            (setf (aref ,(make-slot-accessor-call instance
  169.                                                  structure
  170.                                                  slot)
  171.                        ,index)
  172.                  ,value)
  173.            ,value)
  174.         `(defmethod (setf ,(%accessor-of slot))
  175.              (,value (,instance ,(%name-of structure)))
  176.            (check-type ,value ,(%name-of (%type-of slot)))
  177.            (setf ,(make-slot-accessor-call instance structure slot)
  178.                  ,value)
  179.            ,value))))
  180.  
  181. (defun parse-slot-definition (offset slot-definition)
  182.   (check-type slot-definition list)
  183.   (destructuring-bind (name &key accessor (count 1) type)
  184.       slot-definition
  185.     (check-type name symbol)
  186.     (check-type accessor symbol)
  187.     (check-type count (integer 1))
  188.     (check-type type symbol)
  189.     (make-instance '%slot
  190.                    :accessor accessor
  191.                    :count count
  192.                    :name name
  193.                    :offset offset
  194.                    :type (%symbol-type type))))
  195.  
  196. (defun parse-slot-definitions (offset slot-definitions)
  197.   (mapcar #'(lambda (slot-definition)
  198.               (let ((slot
  199.                      (parse-slot-definition offset
  200.                                             slot-definition)))
  201.                 (incf offset (%size-of slot))
  202.                 slot))
  203.           slot-definitions))
  204.  
  205. (defun parse-structure-definition
  206.     (name slot-definitions superstructure-name)
  207.   (let* ((superstructure
  208.           (canonicalize-superstructure superstructure-name))
  209.          (offset (%size-of superstructure))
  210.          (slots
  211.           (parse-slot-definitions offset slot-definitions)))
  212.     (make-instance '%structure
  213.                    :constructor (symbolicate '%make- name)
  214.                    :name name
  215.                    :offset offset
  216.                    :size (reduce #'+ slots :key #'%size-of)
  217.                    :slots slots
  218.                    :superstructure superstructure)))
  219.  
  220. (defmacro define-binary-structure
  221.     (name (&optional superstructure-name) &body slot-definitions)
  222.   (check-type name symbol)
  223.   (check-type superstructure-name (or null symbol))
  224.   (let ((structure
  225.          (parse-structure-definition name
  226.                                      slot-definitions
  227.                                      superstructure-name)))
  228.     `(progn
  229.        ,(make-defstruct-form structure)
  230.  
  231.        ,@(loop for slot in (%slots-of structure)
  232.                collect (make-slot-reader-method structure slot)
  233.                collect (make-slot-writer-method structure slot))
  234.        
  235.        ,(make-structure-reader-method structure)
  236.        ',name)))
  237.  
  238. (macroexpand
  239.   `(define-binary-structure Sa ()
  240.      (sa :accessor Sa-sa
  241.          :type k.binary.integers:uint8)
  242.      (sb :accessor Sa-sb
  243.          :count 3
  244.          :type k.binary.integers:uint8)
  245.      (sc :accessor Sa-sc
  246.          :type k.binary.integers:uint32)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement