aboutsummaryrefslogtreecommitdiffstats
path: root/test/src
diff options
context:
space:
mode:
authorStefan Monnier2023-12-25 22:32:17 -0500
committerStefan Monnier2023-12-27 23:45:51 -0500
commita4efbe4c499623b33882a770c896ebfd31459ce9 (patch)
treed2cc04218080798dcfd80d6e881e6a6ff6b5a647 /test/src
parent8f571769e155a214ae2f9f760dd179b687d9982e (diff)
downloademacs-a4efbe4c499623b33882a770c896ebfd31459ce9.tar.gz
emacs-a4efbe4c499623b33882a770c896ebfd31459ce9.zip
New special form `handler-bind`
AFAIK, this provides the same semantics as Common Lisp's `handler-bind`, modulo the differences about how error objects and conditions are represented. * lisp/subr.el (handler-bind): New macro. * src/eval.c (pop_handler): New function. (Fhandler_Bind_1): New function. (signal_or_quit): Handle new handlertypes `HANDLER` and `SKIP_CONDITIONS`. (find_handler_clause): Simplify. (syms_of_eval): Defsubr `Fhandler_bind_1`. * doc/lispref/control.texi (Handling Errors): Add `handler-bind`. * test/src/eval-tests.el (eval-tests--handler-bind): New test. * lisp/emacs-lisp/lisp-mode.el (lisp-font-lock-keywords): Move 'handler-bind' from CL-only to generic Lisp. (handler-bind): Remove indentation setting, it now lives in the macro definition.
Diffstat (limited to 'test/src')
-rw-r--r--test/src/eval-tests.el37
1 files changed, 37 insertions, 0 deletions
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 4589763b2f5..f288b985579 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -282,4 +282,41 @@ expressions works for identifiers starting with period."
282 (should-error (defvaralias 'eval-tests--my-c 'eval-tests--my-d) 282 (should-error (defvaralias 'eval-tests--my-c 'eval-tests--my-d)
283 :type 'cyclic-variable-indirection)) 283 :type 'cyclic-variable-indirection))
284 284
285(ert-deftest eval-tests--handler-bind ()
286 ;; A `handler-bind' has no effect if no error is signaled.
287 (should (equal (catch 'tag
288 (handler-bind ((error (lambda (_err) (throw 'tag 'wow))))
289 'noerror))
290 'noerror))
291 ;; The handler is called from within the dynamic extent where the
292 ;; error is signaled, unlike `condition-case'.
293 (should (equal (catch 'tag
294 (handler-bind ((error (lambda (_err) (throw 'tag 'err))))
295 (list 'inner-catch
296 (catch 'tag
297 (user-error "hello")))))
298 '(inner-catch err)))
299 ;; But inner condition handlers are temporarily muted.
300 (should (equal (condition-case nil
301 (handler-bind
302 ((error (lambda (_err)
303 (signal 'wrong-type-argument nil))))
304 (list 'result
305 (condition-case nil
306 (user-error "hello")
307 (wrong-type-argument 'inner-handler))))
308 (wrong-type-argument 'wrong-type-argument))
309 'wrong-type-argument))
310 ;; Handlers do not apply to the code run within the handlers.
311 (should (equal (condition-case nil
312 (handler-bind
313 ((error (lambda (_err)
314 (signal 'wrong-type-argument nil)))
315 (wrong-type-argument
316 (lambda (_err) (user-error "wrong-type-argument"))))
317 (user-error "hello"))
318 (wrong-type-argument 'wrong-type-argument)
319 (error 'plain-error))
320 'wrong-type-argument)))
321
285;;; eval-tests.el ends here 322;;; eval-tests.el ends here