From a3499940cc7937384f02b6167d127393ea4943ab Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 8 Jul 2021 12:36:40 -0700 Subject: invoke the SKIP-PROPERTY restart established right after the handler This should better preserve the semantics of the sequencing combinators. Signed-off-by: Sean Whitton --- src/combinator.lisp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/combinator.lisp') diff --git a/src/combinator.lisp b/src/combinator.lisp index 1ff2152..fdb56e9 100644 --- a/src/combinator.lisp +++ b/src/combinator.lisp @@ -65,15 +65,32 @@ Usage notes: (propappunapply (choose-propapp)))))) (setf (get ',name 'inline-combinator) t))) +(defun skip-property-restarts () + (loop for restart in (compute-restarts) + when (eql 'skip-property (restart-name restart)) + collect restart)) + +;; There can be multiple SKIP-PROPERTY restarts established at once, and we +;; need this handler to invoke the one established by WITH-SKIP-PROPERTY right +;; after we establish this handler. (defmacro with-skip-failed-changes (&body forms) - `(handler-bind ((failed-change - (lambda (c) - (with-indented-inform - (apply #'informat t - (simple-condition-format-control c) - (simple-condition-format-arguments c))) - (invoke-restart 'skip-property)))) - ,@forms)) + (with-gensyms (old-restarts) + `(let ((,old-restarts (skip-property-restarts))) + (handler-bind ((failed-change + (lambda (c) + (with-indented-inform + (apply #'informat t + (simple-condition-format-control c) + (simple-condition-format-arguments c))) + ;; We can't just use NSET-DIFFERENCE and take the + ;; LASTCAR because NSET-DIFFERENCE provides no + ;; ordering guarantees. + (loop with chosen + for restart in (skip-property-restarts) + unless (member restart ,old-restarts) + do (setq chosen restart) + finally (invoke-restart chosen))))) + ,@forms)))) ;; N.B. if PROPAPP appears in FORM then it will get evaluated more than once. (defmacro with-skip-property (propapp form) -- cgit v1.2.3