diff options
| author | Stefan Monnier | 2023-12-25 22:32:17 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2024-01-04 16:32:53 -0500 |
| commit | 5ba75e183c60aff50949587c21066e876dabfbda (patch) | |
| tree | db29f1ea2ef53d51ebb7ed1b8be999a664498f89 /test/src | |
| parent | 225710ba79c10b53b6ba320327ca31192ca72387 (diff) | |
| download | emacs-5ba75e183c60aff50949587c21066e876dabfbda.tar.gz emacs-5ba75e183c60aff50949587c21066e876dabfbda.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 e4b18ec7849..9ac117859dd 100644 --- a/test/src/eval-tests.el +++ b/test/src/eval-tests.el | |||
| @@ -303,4 +303,41 @@ expressions works for identifiers starting with period." | |||
| 303 | (should (eq 'bar (default-value 'eval-tests/buffer-local-var))) | 303 | (should (eq 'bar (default-value 'eval-tests/buffer-local-var))) |
| 304 | (should (eq 'bar eval-tests/buffer-local-var))))) | 304 | (should (eq 'bar eval-tests/buffer-local-var))))) |
| 305 | 305 | ||
| 306 | (ert-deftest eval-tests--handler-bind () | ||
| 307 | ;; A `handler-bind' has no effect if no error is signaled. | ||
| 308 | (should (equal (catch 'tag | ||
| 309 | (handler-bind ((error (lambda (_err) (throw 'tag 'wow)))) | ||
| 310 | 'noerror)) | ||
| 311 | 'noerror)) | ||
| 312 | ;; The handler is called from within the dynamic extent where the | ||
| 313 | ;; error is signaled, unlike `condition-case'. | ||
| 314 | (should (equal (catch 'tag | ||
| 315 | (handler-bind ((error (lambda (_err) (throw 'tag 'err)))) | ||
| 316 | (list 'inner-catch | ||
| 317 | (catch 'tag | ||
| 318 | (user-error "hello"))))) | ||
| 319 | '(inner-catch err))) | ||
| 320 | ;; But inner condition handlers are temporarily muted. | ||
| 321 | (should (equal (condition-case nil | ||
| 322 | (handler-bind | ||
| 323 | ((error (lambda (_err) | ||
| 324 | (signal 'wrong-type-argument nil)))) | ||
| 325 | (list 'result | ||
| 326 | (condition-case nil | ||
| 327 | (user-error "hello") | ||
| 328 | (wrong-type-argument 'inner-handler)))) | ||
| 329 | (wrong-type-argument 'wrong-type-argument)) | ||
| 330 | 'wrong-type-argument)) | ||
| 331 | ;; Handlers do not apply to the code run within the handlers. | ||
| 332 | (should (equal (condition-case nil | ||
| 333 | (handler-bind | ||
| 334 | ((error (lambda (_err) | ||
| 335 | (signal 'wrong-type-argument nil))) | ||
| 336 | (wrong-type-argument | ||
| 337 | (lambda (_err) (user-error "wrong-type-argument")))) | ||
| 338 | (user-error "hello")) | ||
| 339 | (wrong-type-argument 'wrong-type-argument) | ||
| 340 | (error 'plain-error)) | ||
| 341 | 'wrong-type-argument))) | ||
| 342 | |||
| 306 | ;;; eval-tests.el ends here | 343 | ;;; eval-tests.el ends here |