blob: de36c51a8de06c926ddcf34fd1f6da1940e9be09 (
plain)
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
47
48
49
50
51
|
;;;
;;; Lisp references: pointer-like place locators that can be passed around.
;;;
;;; Copyright 2012 Kaz Kylheku <kaz@kylheku.com>
;;;
;;; How to use:
;;;
;;; Produce a reference which "lifts" the place designated
;;; by form P:
;;;
;;; (ref p)
;;;
;;; Dereference a reference R to designate the original place:
;;;
;;; (deref r)
;;; (setf (deref r) 42) ;; store new value 42
;;;
;;; Shorthand notation instead of writing a lot of (deref)
;;; Over FORMS, A is a symbol macro which expands to
;;; (DEREF RA), B expands to (DEREF RB):
;;;
;;; (with-refs ((a ra) (b rb) ...)
;;;
;;; ... forms)
;;;
(defstruct ref
(get-func)
(set-func))
(defun deref (ref)
(funcall (ref-get-func ref)))
(defun (setf deref) (val ref)
(funcall (ref-set-func ref) val))
(defmacro ref (place-expression &environment env)
(multiple-value-bind (temp-syms val-forms
store-vars store-form access-form)
(get-setf-expansion place-expression env)
(when (cdr store-vars)
(error "REF: cannot take ref of multiple-value place"))
`(multiple-value-bind (,@temp-syms) (values ,@val-forms)
(make-ref
:get-func (lambda () ,access-form)
:set-func (lambda (,@store-vars) ,store-form)))))
(defmacro with-refs ((&rest ref-specs) &body forms)
`(symbol-macrolet
,(loop for (var ref) in ref-specs
collecting (list var `(deref ,ref)))
,@forms))
|