diff options
| author | Stefan Monnier | 2023-12-25 22:32:17 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2023-12-27 23:45:51 -0500 |
| commit | a4efbe4c499623b33882a770c896ebfd31459ce9 (patch) | |
| tree | d2cc04218080798dcfd80d6e881e6a6ff6b5a647 /test/src | |
| parent | 8f571769e155a214ae2f9f760dd179b687d9982e (diff) | |
| download | emacs-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.el | 37 |
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 |