Skip to content

Commit

Permalink
Prevent infinite loop in CCL compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
ruricolist committed Feb 13, 2024
1 parent 88d7086 commit 284bae5
Showing 1 changed file with 16 additions and 9 deletions.
25 changes: 16 additions & 9 deletions functions.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,22 @@ From LispWorks."
(declare (ignore args))
(values))

(defloop repeat-until-stable (fn x &key (test 'eql) max-depth)
(defun repeat-until-stable (fn x &key (test 'eql) max-depth)
"Takes a single-argument FN and calls (fn x), then (fn (fn x)), and so on
until the result doesn't change according to TEST. If MAX-DEPTH is specified
then FN will be called at most MAX-DEPTH times even if the result is still changing."
(if (eql 0 max-depth)
x
(let ((next (funcall fn x)))
(if (funcall test next x)
x
(repeat-until-stable fn next :test test
:max-depth (when max-depth
(1- max-depth)))))))
(declare ((or symbol function) fn test)
((or (integer *) null) max-depth))
(let ((fn (ensure-function fn)))
(with-two-arg-test (test)
(with-boolean (max-depth)
(nlet repeat-until-stable ((x x)
(max-depth max-depth))
(if (eql 0 max-depth)
x
(let ((next (funcall fn x)))
(if (funcall test next x)
x
(repeat-until-stable next
(boolean-when max-depth
(1- max-depth)))))))))))

0 comments on commit 284bae5

Please sign in to comment.