#:whitespace-char-p
#:slot-uninitialized
#:with-gensyms #:let*/gensyms #:with-places
- #:locp #:locf #:ref #:with-locatives))
+ #:locp #:locf #:ref #:with-locatives
+ #:update-place #:update-place-after
+ #:incf-after #:decf-after))
(in-package #:mdw.base)
(defmacro compile-time-defun (name args &body body)
((#\space #\tab #\newline #\return #\vt #\formfeed) t)
(t nil)))
+(defmacro nlet (name binds &body body)
+ "Scheme's named let."
+ (multiple-value-bind (vars vals)
+ (loop for bind in binds
+ for (var val) = (pairify bind nil)
+ collect var into vars
+ collect val into vals
+ finally (return (values vars vals)))
+ `(labels ((,name ,vars
+ ,@body))
+ (,name ,@vals))))
+
+(defmacro while (cond &body body)
+ "If COND is false, evaluate to nil; otherwise evaluate BODY and try again."
+ `(loop
+ (unless `cond (return))
+ ,@body))
+
(declaim (ftype (function nil ()) slot-unitialized))
(defun slot-uninitialized ()
"A function which signals an error. Can be used as an initializer form in
body))))))))))
(car (more (mapcar #'pairify (listify places))))))))
+(defmacro update-place (op place arg &environment env)
+ "Update PLACE with the value of OP PLACE ARG, returning the new value."
+ (with-places (:environment env) (place)
+ `(setf ,place (,op ,place ,arg))))
+(defmacro update-place-after (op place arg &environment env)
+ "Update PLACE with the value of OP PLACE ARG, returning the old value."
+ (with-places (:environment env) (place)
+ (with-gensyms (x)
+ `(let ((,x ,place))
+ (setf ,place (,op ,x ,arg))
+ ,x))))
+(defmacro incf-after (place &optional (by 1))
+ "Increment PLACE by BY, returning the old value."
+ `(update-place-after + ,place ,by))
+(defmacro decf-after (place &optional (by 1))
+ "Decrement PLACE by BY, returning the old value."
+ `(update-place-after - ,place ,by))
+
+
(defstruct (loc (:predicate locp) (:constructor make-loc (reader writer)))
"Locative data type. See `locf' and `ref'."
(reader (slot-uninitialized) :type function)