From 217b38398bfa523c48f630b06b21427974d93e1d Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Fri, 10 Dec 2021 21:38:58 -0800 Subject: Rewrite helpful--tree-any-p as a loop Fixes #279 --- CHANGELOG.md | 2 ++ helpful.el | 18 +++++++++++------- test/helpful-unit-test.el | 4 ++++ 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)))) -- cgit v1.0