chiark / gitweb /
Ignore boring files.
[lisp] / mdw-base.lisp
index 3111832bc5b5c31fafad68573be2ab1872d9cc74..21948fa0311a5aa5a273621c172b03ff2445e36f 100644 (file)
@@ -31,7 +31,9 @@ (defpackage #:mdw.base
           #: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)
@@ -86,6 +88,24 @@ (defun whitespace-char-p (ch)
     ((#\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
@@ -155,6 +175,25 @@ (defmacro with-places ((&key environment) places &body body)
                                          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)