From 62db6cd6ef35a8dc465538706f89e658db09661a Mon Sep 17 00:00:00 2001
From: Eduardo Julian
Date: Tue, 1 May 2018 19:31:21 -0400
Subject: Allow giving names to loops that can be used instead of "recur".
---
 stdlib/source/lux.lux | 75 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 46 insertions(+), 29 deletions(-)
diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 10e188769..dc469633f 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -4460,7 +4460,7 @@
                 ## else-branch
                 \"???\")"}
   (if (n/= +0 (n/% +2 (list/size tokens)))
-    (fail "cond requires an even number of arguments.")
+    (fail "cond requires an uneven number of arguments.")
     (case (list/reverse tokens)
       (^ (list& else branches'))
       (return (list (list/fold (: (-> [Code Code] Code Code)
@@ -5287,36 +5287,53 @@
                      x init]
                 (if (< 10 count)
                   (recur (i/inc count) (f x))
+                  x))
+
+              "Loops can also be given custom names."
+              (loop my-loop
+                [count 0
+                 x init]
+                (if (< 10 count)
+                  (my-loop (i/inc count) (f x))
                   x)))}
-  (case tokens
-    (^ (list [_ (#Tuple bindings)] body))
-    (let [pairs (as-pairs bindings)
-          vars (list/map first pairs)
-          inits (list/map second pairs)]
-      (if (every? symbol? inits)
-        (do Monad
-          [inits' (: (Meta (List Ident))
-                     (case (monad/map Monad get-ident inits)
-                       (#Some inits') (return inits')
-                       #None          (fail "Wrong syntax for loop")))
-           init-types (monad/map Monad find-type inits')
-           expected get-expected-type]
-          (return (list (` (("lux check" (-> (~+ (list/map type-to-code init-types))
-                                             (~ (type-to-code expected)))
-                             (function ((~ (symbol$ ["" "recur"])) (~+ vars))
-                               (~ body)))
-                            (~+ inits))))))
-        (do Monad
-          [aliases (monad/map Monad
-                              (: (-> Code (Meta Code))
-                                 (function (_ _) (gensym "")))
-                              inits)]
-          (return (list (` (let [(~+ (interleave aliases inits))]
-                             (.loop [(~+ (interleave vars aliases))]
-                               (~ body)))))))))
+  (let [?params (case tokens
+                  (^ (list name [_ (#Tuple bindings)] body))
+                  (#.Some [name bindings body])
+                  
+                  (^ (list [_ (#Tuple bindings)] body))
+                  (#.Some [(symbol$ ["" "recur"]) bindings body])
 
-    _
-    (fail "Wrong syntax for loop")))
+                  _
+                  #.None)]
+    (case ?params
+      (#.Some [name bindings body])
+      (let [pairs (as-pairs bindings)
+            vars (list/map first pairs)
+            inits (list/map second pairs)]
+        (if (every? symbol? inits)
+          (do Monad
+            [inits' (: (Meta (List Ident))
+                       (case (monad/map Monad get-ident inits)
+                         (#Some inits') (return inits')
+                         #None          (fail "Wrong syntax for loop")))
+             init-types (monad/map Monad find-type inits')
+             expected get-expected-type]
+            (return (list (` (("lux check" (-> (~+ (list/map type-to-code init-types))
+                                               (~ (type-to-code expected)))
+                               (function ((~ name) (~+ vars))
+                                 (~ body)))
+                              (~+ inits))))))
+          (do Monad
+            [aliases (monad/map Monad
+                                (: (-> Code (Meta Code))
+                                   (function (_ _) (gensym "")))
+                                inits)]
+            (return (list (` (let [(~+ (interleave aliases inits))]
+                               (.loop [(~+ (interleave vars aliases))]
+                                 (~ body)))))))))
+
+      #.None
+      (fail "Wrong syntax for loop"))))
 
 (macro: #export (^slots tokens)
   {#.doc (doc "Allows you to extract record members as local variables with the same names."
-- 
cgit v1.2.3