-
Notifications
You must be signed in to change notification settings - Fork 2
/
astruct.el
46 lines (41 loc) · 1.66 KB
/
astruct.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
;; Implements structure as alists prefixed by the structure type name.
;; json uses this kind of alist.
(defun alistp% (slow fast)
(or (null slow)
(and (not (eq slow fast))
(consp slow)
(consp (car slow))
(listp fast)
(listp (cdr fast))
(alistp% (cdr slow) (cddr fast)))))
(defun alistp (object)
(or (null object)
(and (consp object)
(alistp% object (cdr object)))))
(assert (not (alistp '#1=((1 . 2) . #1#))))
(assert (not (alistp '((1 . 2) (3 . 4) . x))))
(assert (not (alistp '((1 . 2) (3 . 4) x (5 . 6)))))
(assert (alistp '((1 . 2) (3 . 4) (5 . 6))))
(assert (alistp '((1 . 2) (3 . 4))))
(assert (alistp '((1 . 2))))
(assert (alistp '()))
(defmacro define-structure (name fields)
`(progn
(defun* ,(intern (format "make-%s" name)) (&rest fields &key ,@fields)
(cons ',name (mapcar* (function cons) ',fields fields)))
,@(mapcan (lambda (field)
(list
`(defun ,(intern (format "%s-%s" name field)) (structure)
(cdr (assoc ',field (cdr structure))))
`(defun ,(intern (format "set-%s-%s" name field)) (structure value)
(let ((entry (assoc ',field (cdr structure))))
(if (null entry)
(push (cons ',field value) (cdr structure))
(setf (cdr entry) value))
value))
`(defun ,(intern (format "%s-p" name)) (object)
(and (consp object)
(eq ',name (car object))
(alistp (cdr object))))))
fields)
',name))