aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--helpful.el18
-rw-r--r--test/helpful-unit-test.el4
3 files changed, 17 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c0d1d4..8d757f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ Fixed issue with displaying circular data structures.
Fixed a crash in `helpful-variable` in files that weren't
syntactically valid lisp.
+Fixed stack overflow in macroexpanding large s-expressions (#279).
+
# v0.18
Show the original value for custom variables whose value has changed.
diff --git a/helpful.el b/helpful.el
index b811811..3e064d7 100644
--- a/helpful.el
+++ b/helpful.el
@@ -1317,13 +1317,17 @@ If it fails, attempt to partially macroexpand FORM."
(defun helpful--tree-any-p (pred tree)
"Walk TREE, applying PRED to every subtree.
Return t if PRED ever returns t."
- (cond
- ((null tree) nil)
- ((funcall pred tree) t)
- ((not (consp tree)) nil)
- (t (or
- (helpful--tree-any-p pred (car tree))
- (helpful--tree-any-p pred (cdr tree))))))
+ (catch 'found
+ (let ((stack (list tree)))
+ (while stack
+ (let ((next (pop stack)))
+ (cond
+ ((funcall pred next)
+ (throw 'found t))
+ ((consp next)
+ (push (car next) stack)
+ (push (cdr next) stack))))))
+ nil))
(defun helpful--find-by-macroexpanding (buf sym callable-p)
"Search BUF for the definition of SYM by macroexpanding
diff --git a/test/helpful-unit-test.el b/test/helpful-unit-test.el
index 1fbf87c..510396c 100644
--- a/test/helpful-unit-test.el
+++ b/test/helpful-unit-test.el
@@ -1072,3 +1072,7 @@ find the source code."
"Ensure that we can describe an autoloaded function
that has advice attached before it is loadedl."
(helpful-function 'ruby-mode))
+
+(ert-deftest helpful--tree-any-p ()
+ (should (helpful--tree-any-p (lambda (x) (eq x 1)) '((((1))))))
+ (should (helpful--tree-any-p (lambda (x) (eq x 1)) (cons 2 1))))