summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-11-13 17:37:55 -0800
committerKaz Kylheku <kaz@kylheku.com>2013-11-13 17:37:55 -0800
commit8d0fd244e013683b049d86b6599de369bbad592f (patch)
treea7c3cd91352615ac138b8f48cc028368fa558858
parent47d04de6478f48c6296198776b0ed572e736b008 (diff)
downloadlisp-snippets-8d0fd244e013683b049d86b6599de369bbad592f.tar.gz
lisp-snippets-8d0fd244e013683b049d86b6599de369bbad592f.tar.bz2
lisp-snippets-8d0fd244e013683b049d86b6599de369bbad592f.zip
DEFTAIL: bugfix when function directly recurses. The return-from in the
generated FLET then references the FLET rather than the surrounding function. Fixed by introducing anon block as the target of the return instead.
-rw-r--r--tail-recursion.lisp22
1 files changed, 12 insertions, 10 deletions
diff --git a/tail-recursion.lisp b/tail-recursion.lisp
index 635982e..8381345 100644
--- a/tail-recursion.lisp
+++ b/tail-recursion.lisp
@@ -252,6 +252,7 @@
(defmacro deftail (name lambda-list &body body)
(let ((escape (gensym "ESCAPE-"))
(other-tails `(,name))
+ (anon-block (gensym))
(docstring)
(decls))
(when (stringp (first body))
@@ -267,13 +268,14 @@
`(defun ,name (,@lambda-list &aux (,escape *tail-escape*))
,@docstring
,@decls
- (flet (,@(loop for other in other-tails
- collecting `(,other (&rest args)
- (return-from ,name
- (let ((*tail-escape* ,escape))
- (tail-call #',other args)))))
- (tail-call (fun args)
- (let ((*tail-escape* ,escape))
- (tail-call fun args))))
- (let ((*tail-escape* nil))
- ,@body)))))
+ (block ,anon-block
+ (flet (,@(loop for other in other-tails
+ collecting `(,other (&rest args)
+ (return-from ,anon-block
+ (let ((*tail-escape* ,escape))
+ (tail-call #',other args)))))
+ (tail-call (fun args)
+ (let ((*tail-escape* ,escape))
+ (tail-call fun args))))
+ (let ((*tail-escape* nil))
+ ,@body))))))