From 8e929366ee8e10b6380090a58acd71a34c0de5f7 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 16 Jan 2012 23:16:22 -0800 Subject: Adding refs. --- refs.lisp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 refs.lisp (limited to 'refs.lisp') diff --git a/refs.lisp b/refs.lisp new file mode 100644 index 0000000..de36c51 --- /dev/null +++ b/refs.lisp @@ -0,0 +1,51 @@ +;;; +;;; Lisp references: pointer-like place locators that can be passed around. +;;; +;;; Copyright 2012 Kaz Kylheku +;;; +;;; 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)) -- cgit v1.2.3