ee7247080256

Add `macroexpand-iterate`
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 18 Sep 2016 12:50:45 +0000
parents 6aeaaa9a56bf
children ca0a5dd96216
branches/tags (none)
files losh.lisp package.lisp

Changes

--- a/losh.lisp	Sun Sep 18 12:50:38 2016 +0000
+++ b/losh.lisp	Sun Sep 18 12:50:45 2016 +0000
@@ -1,5 +1,6 @@
 (in-package #:losh)
 
+
 ;;;; Chili Dogs
 (defmacro defun-inlineable (name &body body)
   `(progn
@@ -1070,6 +1071,55 @@
         (next ,control)))))
 
 
+(defun keywordize-clause (clause)
+  (iterate
+    (for (k v . nil) :on clause :by #'cddr)
+    (collect (ensure-keyword k))
+    (collect v)))
+
+(defun keywordize-some-of-clause (clause)
+  ; please kill me
+  (append (take 2 clause) (keywordize-clause (nthcdr 2 clause))))
+
+(defun macroexpand-iterate (clause)
+  "Macroexpand the given iterate clause/driver.
+
+  Example:
+
+    (macroexpand-iterate '(averaging (+ x 10) :into avg))
+    =>
+    (PROGN
+     (FOR #:COUNT665 :FROM 0)
+     (FOR AVG :FIRST (+ X 10) :THEN
+      (/ (+ (* AVG #:COUNT665) (+ X 10)) (1+ #:COUNT665))))
+
+  "
+  ;; Given a clause like (for foo in-whatever bar) we need to:
+  ;;
+  ;; 1. Look up the appropriate macro (confusingly named via gentemp).  This
+  ;;    requires calling `iterate::get-clause-info` with an appropriately-formed
+  ;;    clause.
+  ;;
+  ;;    The first item in the clause must be a normal (non-keyword) symbol, but
+  ;;    the rest of the clause keywords must be actual keyword symbols.
+  ;;
+  ;; 2. Build the appropriate list to `macroexpand-1`.  This should be of the
+  ;;    form `(the-wierdly-named-macro ...)`.
+  ;;
+  ;;    Note that the macro will be expecting the clause to come in as keyword
+  ;;    arguments, so unlike in step 1 ALL the clause keywords need to be actual
+  ;;    keywords, including the first.
+  ;;
+  ;; We'll also bind `iterate::*result-var*` so any macros that use it won't
+  ;; immediately shit the bed.
+  (let ((iterate::*result-var* 'iterate::*result-var*))
+    (values
+      (macroexpand-1 (cons (iterate::clause-info-function
+                             (iterate::get-clause-info
+                               (keywordize-some-of-clause clause)))
+                           (keywordize-clause clause))))))
+
+
 ;;;; Distributions
 (defun prefix-sums (list)
   "Return a list of the prefix sums of the numbers in `list`.
--- a/package.lisp	Sun Sep 18 12:50:38 2016 +0000
+++ b/package.lisp	Sun Sep 18 12:50:45 2016 +0000
@@ -120,7 +120,8 @@
     #:cycling
     #:for-nested
     #:within-radius
-    #:skip-origin))
+    #:skip-origin
+    #:macroexpand-iterate))
 
 (defpackage #:losh.distributions
   (:documentation "Utilities for calculating statistical... things.")