aboutsummaryrefslogtreecommitdiff
path: root/src/combinator.lisp
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-07-08 12:36:40 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-07-10 21:31:38 -0700
commita3499940cc7937384f02b6167d127393ea4943ab (patch)
tree6921e1cbe851b34865254eaaac4ce7b9e81768b8 /src/combinator.lisp
parente74824042e28186d1654c6a8d5faa3de58fc263d (diff)
downloadconsfigurator-a3499940cc7937384f02b6167d127393ea4943ab.tar.gz
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 <spwhitton@spwhitton.name>
Diffstat (limited to 'src/combinator.lisp')
-rw-r--r--src/combinator.lisp33
1 files changed, 25 insertions, 8 deletions
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)