* bug#68075: 30.0.50; New special form `handler-bind` @ 2023-12-28 6:33 Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 8:03 ` Eli Zaretskii 0 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 6:33 UTC (permalink / raw) To: 68075; +Cc: monnier Package: Emacs Version: 30.0.50 I have now pushed to `scratch/handler-bind` a set of patches I'd like to commit to `master`. They add the new special form `handler-bind`, which provides a functionality a bit halfway between `condition-case` and `signal-hook-function`. Among other things, this allows us to fix bug#11218, bug#65267, and bug#67196. It also makes it possible to move code out of `signal_or_quit`. The complete log can be found below, but the oneliners are: New special form `handler-bind` (eval-expression): Fix bug#67196 ert.el: Use `handler-bind` to record backtraces Fix ert-tests.el for the new `handler-bind` code Use handler-bind to repair bytecomp-tests emacs-module-tests.el (mod-test-non-local-exit-signal-test): Repair test startup.el: Use `handler-bind` to implement `--debug-init` Move batch backtrace code to `top_level_2` (macroexp--with-extended-form-stack): Use plain `let` eval.c: Add new var `lisp-eval-depth-reserve` (signal_or_quit): Preserve error object identity (backtrace-on-redisplay-error): Use `handler-bind` As you can see, the first commit adds the new feature, and subsequent ones basically make use of it in various different places. Among those commits, I'll note the introduction of a new variable `lisp-eval-depth-reserve`, which lets us control how much Emacs can grow `max-lisp-eval-depth` to run the debugger. This is not indispensable, but seemed like a good idea. I also subtly changed the way errors are built such that we can rely on the error object being `eq` to itself as it moves up from the call to `signal` up to its `condition-case` handler, which should make it possible to keep extra info about it in an `eq` hashtable, for example. Comments, objections? Stefan commit a4efbe4c499623b33882a770c896ebfd31459ce9 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Dec 25 22:32:17 2023 -0500 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. commit 19f1d2a9f5111a2f06003f45f3af2a39c7029047 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Dec 18 23:47:56 2023 -0500 (eval-expression): Fix bug#67196 * lisp/simple.el (eval-expression--debug): New function. (eval-expression): Use it together with `handler-bind` instead of let-binding `debug-on-error`. commit ae21819496a7f003c4d4e185204533660197daaa Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Dec 18 23:57:45 2023 -0500 ert.el: Use `handler-bind` to record backtraces * lisp/emacs-lisp/ert.el (ert--should-signal-hook): Delete function. (ert--expand-should-1): Don't bind `signal-hook-function`. (ert--test-execution-info): Remove `next-debugger` slot. (ert--run-test-debugger): Adjust to new calling convention. Pass the `:backtrace-base` info to the debugger. (ert--run-test-internal): Use `handler-bind` rather than let-binding `debugger` and `debug-on-error`. * lisp/emacs-lisp/ert-x.el (ert-remote-temporary-file-directory): Don't use `defconst` if it's not meant to stay constant (e.g. we let-bind it in tramp-tests.el). commit 89a298b3d2f86e75750617ef7e301372ea5aa46f Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Thu Dec 28 00:46:36 2023 -0500 Fix ert-tests.el for the new `handler-bind` code Now that `ert.el` uses `handler-bind` instead of `debugger`, some details of the behavior have changed. More specifically, three tests are now broken, but these basically tested the failure of ERT's machinery to record errors when ERT was run within a `condition-case`. AFAICT, these tests do not check for a behavior that we want, so rather than "fix" them, I disabled them. * test/lisp/emacs-lisp/ert-tests.el (ert-test-error-debug) (ert-test-fail-debug-with-condition-case) (ert-test-should-failure-debugging): Comment out. (ert-test-with-demoted-errors): It now passes. Bug#11218 is fixed! commit 1c1d2eb3e389bb5e397cd8e1568e4e3129067912 Author: Mattias Engdegård <mattiase@acm.org> Date: Wed Dec 27 11:32:49 2023 +0100 Use handler-bind to repair bytecomp-tests * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--error-frame, bytecomp--byte-op-error-backtrace): Make test pass again and simplify, using handler-bind instead of the previous debugger hack. commit dcf7508c947359866151171a840d99d939c35cdf Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Thu Dec 28 00:49:39 2023 -0500 emacs-module-tests.el (mod-test-non-local-exit-signal-test): Repair test That test relied on `debugger` and `debug-on-signal` in a way that doesn't work with the new ERT code. * test/src/emacs-module-tests.el (mod-test-non-local-exit-signal-test): Use `handler-bind` rather than the debugger. commit 917596160c1c831b3a41b320a0e357e5161cb4c8 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Tue Dec 19 19:46:47 2023 -0500 startup.el: Use `handler-bind` to implement `--debug-init` This provides a more reliable fix for bug#65267 since we don't touch `debug-on-error` nor `debug-ignore-errors` any more. * lisp/startup.el (startup--debug): New function. (startup--load-user-init-file): Use it and `handler-bind` instead of let-binding `debug-on-error`. commit 6a57b9151b149a445daecc211d8f58010e605768 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Wed Dec 20 23:31:39 2023 -0500 Move batch backtrace code to `top_level_2` Move ad-hoc code meant to ease debugging of bootstrap (and batch mode) to `top_level_2` so it doesn't pollute `signal_or_quit`. * src/lisp.h (pop_handler, push_handler_bind): Declare. * src/keyboard.c (top_level_2): Setup an error handler to call `debug-early` when noninteractive. * src/eval.c (pop_handler): Not static any more. (signal_or_quit): Remove special case for noninteractive use. (push_handler_bind): New function, extracted from `Fhandler_bind_1`. (Fhandler_bind_1): Use it. (syms_of_eval): Declare `Qdebug_early__handler`. * lisp/emacs-lisp/debug-early.el (debug-early-backtrace): Weed out frames below `debug-early`. (debug-early--handler): New function. commit 634bf61947606d1b8344ba090fdd0fc098fb5eb6 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Dec 25 23:55:53 2023 -0500 (macroexp--with-extended-form-stack): Use plain `let` `macroexp--with-extended-form-stack` used manual push/pop so that upon non-local exits the "deeper" value is kept, so the error handler gets to know what was the deeper value, so as to be able to compute more precise error locations. Replace this with a `handler-bind` which catches that "deeper" value more explicitly. * lisp/emacs-lisp/bytecomp.el (bytecomp--displaying-warnings): Use `handler-bind` to catch the value of `byte-compile-form-stack` at the time of the error. Also consolidate the duplicated code. * lisp/emacs-lisp/macroexp.el (macroexp--with-extended-form-stack): Use a plain dynbound let-rebinding. commit c89b234405f8fa6c52f83104a46a4a2c3121198f Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Tue Dec 26 23:56:09 2023 -0500 eval.c: Add new var `lisp-eval-depth-reserve` Rather than blindly increase `max-lisp-eval-depth` when entering the debugger or running `signal-hook-function`, use this new "reserve" to keep track of how much we have grown the stack for "debugger" purposes so that for example recursive calls to `signal-hook-function` can't eat up the whole C stack. * src/eval.c (max_ensure_room): Rewrite. (restore_stack_limits): Move before `max_ensure_room`. Rewrite. (call_debugger, signal_or_quit): Adjust calls accordingly. Also grow `max-lisp-eval-depth` for `hander-bind` handlers. (init_eval_once): Don't initialize `max_lisp_eval_depth` here. (syms_of_eval): Initialize it here instead. Add new var `lisp-eval-depth-reserve`. * doc/lispref/eval.texi (Eval): Add `lisp-eval-depth-reserve`. commit b925152bffce30abbd48361af6858cd45b785d84 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Wed Dec 27 15:06:32 2023 -0500 (signal_or_quit): Preserve error object identity Make sure we build the (ERROR-SYMBOL . ERROR-DATA) object only once when signaling an error, so that its `eq` identity can be used. It also gets us a tiny bit closer to having real "error objects" like in most other current programming languages. * src/eval.c (maybe_call_debugger): Change arglist to receive the error object instead of receiving the signal and the data separately. (signal_or_quit): Build the error object right at the beginning so it stays `eq` to itself. Rename the `keyboard_quit` arg to `continuable` so say what it does rather than what it's used for. (signal_quit_p): Change arg to be the error object rather than just the error-symbol. * src/keyboard.c (cmd_error_internal, menu_item_eval_property_1): Adjust calls to `signal_quit_p` accordingly. * test/src/eval-tests.el (eval-tests--error-id): New test. commit 26b7078705ae5b9226c99e370740ab9a4063f20f Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Dec 25 21:41:08 2023 -0500 (backtrace-on-redisplay-error): Use `handler-bind` Reimplement `backtrace-on-redisplay-error` using `push_handler_bind`. This moves the code from `signal_or_quit` to `xdisp.c` and `debug-early.el`. * lisp/emacs-lisp/debug-early.el (debug-early-backtrace): Add `base` arg to strip "internal" frames. (debug--early): New function, extracted from `debug-early`. (debug-early, debug-early--handler): Use it. (debug-early--muted): New function, extracted (translated) from `signal_or_quit`; trim the buffer to a max of 10 backtraces. * src/xdisp.c (funcall_with_backtraces): New function. (dsafe_calln): Use it. (syms_of_xdisp): Defsym `Qdebug_early__muted`. * src/eval.c (redisplay_deep_handler): Delete var. (init_eval, internal_condition_case_n): Don't set it any more. (backtrace_yet): Delete var. (signal_or_quit): Remove special case for `backtrace_on_redisplay_error`. * src/keyboard.c (command_loop_1): Don't set `backtrace_yet` any more. * src/lisp.h (backtrace_yet): Don't declare. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 6:33 bug#68075: 30.0.50; New special form `handler-bind` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 8:03 ` Eli Zaretskii 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2023-12-28 8:03 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > Cc: monnier@iro.umontreal.ca > Date: Thu, 28 Dec 2023 01:33:09 -0500 > From: Stefan Monnier via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > I have now pushed to `scratch/handler-bind` a set of patches I'd like to > commit to `master`. They add the new special form `handler-bind`, which > provides a functionality a bit halfway between `condition-case` and > `signal-hook-function`. > > Among other things, this allows us to fix bug#11218, bug#65267, and > bug#67196. It also makes it possible to move code out of > `signal_or_quit`. > > The complete log can be found below, but the oneliners are: > > New special form `handler-bind` > (eval-expression): Fix bug#67196 > ert.el: Use `handler-bind` to record backtraces > Fix ert-tests.el for the new `handler-bind` code > Use handler-bind to repair bytecomp-tests > emacs-module-tests.el (mod-test-non-local-exit-signal-test): Repair test > startup.el: Use `handler-bind` to implement `--debug-init` > Move batch backtrace code to `top_level_2` > (macroexp--with-extended-form-stack): Use plain `let` > eval.c: Add new var `lisp-eval-depth-reserve` > (signal_or_quit): Preserve error object identity > (backtrace-on-redisplay-error): Use `handler-bind` > > As you can see, the first commit adds the new feature, and subsequent > ones basically make use of it in various different places. > > Among those commits, I'll note the introduction of a new variable > `lisp-eval-depth-reserve`, which lets us control how much Emacs can grow > `max-lisp-eval-depth` to run the debugger. This is not indispensable, > but seemed like a good idea. I also subtly changed the way errors > are built such that we can rely on the error object being `eq` to itself > as it moves up from the call to `signal` up to its `condition-case` > handler, which should make it possible to keep extra info about it > in an `eq` hashtable, for example. > > Comments, objections? Assuming by the above you meant that the branch is from your POV ready to land on master, please find some review comments below. > diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi > index d4bd8c1..4107963 100644 > --- a/doc/lispref/control.texi > +++ b/doc/lispref/control.texi > @@ -2293,6 +2293,44 @@ Handling Errors > @code{condition-case-unless-debug} rather than @code{condition-case}. > @end defmac > > +Occasionally, we want to catch some errors and record some information > +about the conditions in which they occurred, such as the full > +backtrace, or the current buffer. This kinds of information is sadly > +not available in the handlers of a @code{condition-case} because the > +stack is unwound before running that handler, so the handler is run in > +the dynamic context of the @code{condition-case} rather than that of > +the place where the error was signaled. For those circumstances, you > +can use the following form: The reference to "unwinding the stack before running handler" uses terminology and assumes knowledge we don't generally expect from readers of the ELisp manual. This should be reworded to use the terminology we use in other cases where we talk about "unwinding" and error handlers. > +@defmac handler-bind handlers body@dots{} > +This special form runs @var{body} and if it executes without error, > +the value it returns becomes the value of the @code{handler-bind} > +form. In this case, the @code{handler-bind} has no effect. > + > +@var{handlers} should be a list of elements of the form > +@code{(@var{conditions} @var{handler})} where @var{conditions} is an > +error condition name to be handled, or a list of condition names, and > +@var{handler} should be a form whose evaluation should return a function. CONDITIONs are symbols, aren't they? The above says "condition names", which could be interpreted as if they were strings instead. > +Before running @var{body}, @code{handler-bind} evaluates all the > +@var{handler} forms and installs those handlers to be active during > +the evaluation of @var{body}. These handlers are searched together > +with those installed by @code{condition-case}. This reference to condition-case might confuse: what does condition-case have to do with handler-bind? And if it is expected that handler-bind is used inside condition-case, there should be some text about it, and the examples we hopefully add should illustrate that. > When the innermost > +matching handler is one installed by @code{handler-bind}, the > +@var{handler} function is called with a single argument holding the > +error description. Is "error description" the same as "error name" above? If so, let's please use consistent wording to minimize the chances for confusion and misunderstandings. > +@var{handler} is called in the dynamic context where the error > +happened, without first unwinding the stack, meaning that all the > +dynamic bindings are still in effect, Should we tell something about the effects of lexical-binding on those "dynamic bindings"? > except that all the error > +handlers between the code that signaled the error and the > +@code{handler-bind} are temporarily suspended. Not sure I understand what it means for those handlers to be "suspended". can the text say more about that? > Like any normal > +function, @var{handler} can exit non-locally, typically via > +@code{throw}, or it can return normally. If @var{handler} returns > +normally, it means the handler @emph{declined} to handle the error and > +the search for an error handler is continued where it left off. > +@end defmac I think we should have a couple of examples here, to show the utility of handler-bind and how it is different from condition-case. > +@defopt lisp-eval-depth-reserve > +In order to be able to debug infinite recursion errors, Entry to the ^^^ Typo. > +Lisp debugger increases temporarily the value of > +@code{max-lisp-eval-depth}, if there is little room left, to make sure > +the debugger itself has room to execute. The same happens when > +running the handler of a @code{handler-bind}. Please add here a cross-reference to where handler-bind is documented. > +The variable @code{lisp-eval-depth-reserve} bounds the extra depth > +that Emacs can add to @code{max-lisp-eval-depth} for those > +exceptional circumstances. > +@end defopt I think this should document the default value. > ++++ > +** New special form 'handler-bind'. > +Provides a functionality similar to `condition-case` except it runs the > +handler code without unwinding the stack, such that we can record the > +backtrace and other dynamic state at the point of the error. Please add here a link to the node in the ELisp manual where handler-bind is described. > -(defmacro displaying-byte-compile-warnings (&rest body) > +(defmacro displaying-byte-compile-warnings (&rest body) ;FIXME: Namespace! ^^^^^^^^^^^^^^^^^^ What about this FIXME? > +(defmacro handler-bind (handlers &rest body) > + "Setup error HANDLERS around execution of BODY. > +HANDLERS is a list of (CONDITIONS HANDLER) where > +CONDITIONS should be a list of condition names (symbols) or > +a single condition name and HANDLER is a form whose evaluation ^ A comma is missing there. > +returns a function. > +When an error is signaled during execution of BODY, if that > +error matches CONDITIONS, then the associated HANDLER > +function is called with the error as argument. ^^^^^^^^^^^^^^^^^^^^^^^^^^ "Error" or "condition name"? If "error", then what does "error matches CONDITIONS" mean in practice? > +HANDLERs can either transfer the control via a non-local exit, > +or return normally. If they return normally the search for an ^^^^^^^^^^^^^^ I'd suggest "If a handler returns" instead. There's just one HANDLER involved here, right? > +error handler continues from where it left off." This "from where it left off" sounds confusing: what does it mean? IOW, how is it different from saying If a HANDLER returns normally, other CONDITIONS are searched for a match, and, if found, their HANDLERs are called. Btw, this begs the question: what happens if none of the CONDITIONS match? In particular, what happens if a HANDLER is called, returns normally, and none of the other CONDITIONS match? > + ;; FIXME: Completion support as in `condition-case'? ^^^^^ What about this FIXME? > @@ -317,6 +312,7 @@ call_debugger (Lisp_Object arg) > /* Interrupting redisplay and resuming it later is not safe under > all circumstances. So, when the debugger returns, abort the > interrupted redisplay by going back to the top-level. */ > + /* FIXME: Move this to the redisplay code? */ ^^^^^ And this one? > +DEFUN ("handler-bind-1", Fhandler_bind_1, Shandler_bind_1, 1, MANY, 0, > + doc: /* Setup error handlers around execution of BODYFUN. > +BODYFUN be a function and it is called with no arguments. > +CONDITIONS should be a list of condition names (symbols). > +When an error is signaled during executon of BODYFUN, if that > +error matches one of CONDITIONS, then the associated HANDLER is > +called with the error as argument. > +HANDLER should either transfer the control via a non-local exit, > +or return normally. > +If it returns normally, the search for an error handler continues > +from where it left off. "Where it left off" strikes again... > + specpdl_ref count = SPECPDL_INDEX (); > + max_ensure_room (20); > + /* FIXME: 'handler-bind' makes `signal-hook-function' obsolete? */ > + /* FIXME: Here we still "split" the error object > + into its error-symbol and its error-data? */ > call2 (Vsignal_hook_function, error_symbol, data); > + unbind_to (count, Qnil); FIXMEs again. > top_level_2 (void) > { > - return Feval (Vtop_level, Qnil); > + /* If we're in batch mode, print a backtrace unconditionally when > + encountering an error, to help with debugging. */ > + bool setup_handler = noninteractive; > + if (setup_handler) > + /* FIXME: Should we (re)use `list_of_error` from `xdisp.c`? */ > + push_handler_bind (list1 (Qerror), Qdebug_early__handler, 0); And again. > +;; (ert-deftest ert-test-fail-debug-with-condition-case () > +;; (let ((test (make-ert-test :body (lambda () (ert-fail "failure message"))))) > +;; (condition-case condition > +;; (progn > +;; (let ((ert-debug-on-error t)) > +;; (ert-run-test test)) > +;; (cl-assert nil)) > +;; ((error) > +;; (cl-assert (equal condition '(ert-test-failed "failure message")) t))))) What about this and other places where some code was commented-out, but not removed? Those seem to be tests that you disable - why? Are they no longer pertinent, or do they fail for some reason that should be fixed? Last, but not least: do all the tests in the test suite pass after these changes, both with and without native-compilation? Thanks. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 8:03 ` Eli Zaretskii @ 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 18:12 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 >> Comments, objections? > > Assuming by the above you meant that the branch is from your POV ready > to land on master, > please find some review comments below. That's right (tho I did expect that the doc needed some improvement :-) > The reference to "unwinding the stack before running handler" uses > terminology and assumes knowledge we don't generally expect from > readers of the ELisp manual. This should be reworded to use the > terminology we use in other cases where we talk about "unwinding" and > error handlers. See patch below for my attempt to clarify. >> +@var{handlers} should be a list of elements of the form >> +@code{(@var{conditions} @var{handler})} where @var{conditions} is an >> +error condition name to be handled, or a list of condition names, and >> +@var{handler} should be a form whose evaluation should return a function. > > CONDITIONs are symbols, aren't they? The above says "condition > names", which could be interpreted as if they were strings instead. I took this nomenclature from `condition-case` where we say: [...] Here @var{conditions} is an error condition name to be handled, or a list of condition names (which can include @code{debug} to allow the debugger to run before the handler). I added a mention that these names are symbols. >> +Before running @var{body}, @code{handler-bind} evaluates all the >> +@var{handler} forms and installs those handlers to be active during >> +the evaluation of @var{body}. These handlers are searched together >> +with those installed by @code{condition-case}. > > This reference to condition-case might confuse: what does > condition-case have to do with handler-bind? I'm trying to explain that when looking for a handler, we look both for condition-case handler and handler-bind handlers and we use whichever is "closest", i.e. more deeply nested. So just like a local `condition-case` overrides temporarily an outer one, the same holds not only among `handler-bind`s but also between `condition-case` and `handler-bind` as well. See the patch for my attempt to clarify. >> When the innermost >> +matching handler is one installed by @code{handler-bind}, the >> +@var{handler} function is called with a single argument holding the >> +error description. > > Is "error description" the same as "error name" above? No, it's I like to call the error object: @cindex error description The argument @var{var} is a variable. @code{condition-case} does not bind this variable when executing the @var{protected-form}, only when it handles an error. At that time, it binds @var{var} locally to an @dfn{error description}, which is a list giving the particulars of the error. The error description has the form @code{(@var{error-symbol} . @var{data})}. The handler can refer to this list to decide what to do. For example, if the error is for failure opening a file, the file name is the second element of @var{data}---the third element of the error description. > If so, let's please use consistent wording to minimize the chances for > confusion and misunderstandings. I wasn't familiar with the term "error description" either, but that's apparently what we use in the Texinfo doc, so I used it specifically to try and "use consistent wording" :-) >> +@var{handler} is called in the dynamic context where the error >> +happened, without first unwinding the stack, meaning that all the >> +dynamic bindings are still in effect, > > Should we tell something about the effects of lexical-binding on those > "dynamic bindings"? It's not related to `handler-bind` in any case, so if we want to say something about it, we should do it elsewhere (and I think we already do when we discuss lexical binding). >> except that all the error >> +handlers between the code that signaled the error and the >> +@code{handler-bind} are temporarily suspended. > Not sure I understand what it means for those handlers to be > "suspended". can the text say more about that? Indeed, it's a delicate part of he semantics (the one that introduces the need for the SKIP_CONDITIONS thingy in the C code). Let me know how you like the new text below. > I think we should have a couple of examples here, to show the utility > of handler-bind and how it is different from condition-case. I added two examples. >> +@defopt lisp-eval-depth-reserve >> +In order to be able to debug infinite recursion errors, Entry to the > ^^^ > Typo. Hmm... yes that's not right, thanks. >> +The variable @code{lisp-eval-depth-reserve} bounds the extra depth >> +that Emacs can add to @code{max-lisp-eval-depth} for those >> +exceptional circumstances. >> +@end defopt > I think this should document the default value. OK. >> ++++ >> +** New special form 'handler-bind'. >> +Provides a functionality similar to `condition-case` except it runs the >> +handler code without unwinding the stack, such that we can record the >> +backtrace and other dynamic state at the point of the error. > > Please add here a link to the node in the ELisp manual where > handler-bind is described. OK. >> -(defmacro displaying-byte-compile-warnings (&rest body) >> +(defmacro displaying-byte-compile-warnings (&rest body) ;FIXME: Namespace! > ^^^^^^^^^^^^^^^^^^ > What about this FIXME? Just a namespace uncleanliness I noticed when working on this code. >> +(defmacro handler-bind (handlers &rest body) >> + "Setup error HANDLERS around execution of BODY. >> +HANDLERS is a list of (CONDITIONS HANDLER) where >> +CONDITIONS should be a list of condition names (symbols) or >> +a single condition name and HANDLER is a form whose evaluation > ^ > A comma is missing there. Thanks. >> +returns a function. >> +When an error is signaled during execution of BODY, if that >> +error matches CONDITIONS, then the associated HANDLER >> +function is called with the error as argument. > ^^^^^^^^^^^^^^^^^^^^^^^^^^ > "Error" or "condition name"? The actual error object (aka "error description"). > If "error", then what does "error matches CONDITIONS" mean > in practice? It means that the "type" or "error name" of the error if a "subtype" of one of CONDITIONS. Given that we represent errors as (ERROR-NAME . ERROR-DATA) rather than as objects, the "type" of an error is just the ERROR-NAME symbol. And the "subtyping" relation is defined by the `parent` arg to `define-error`. This is exactly the same as for `condition-case`, of course. >> +HANDLERs can either transfer the control via a non-local exit, >> +or return normally. If they return normally the search for an > ^^^^^^^^^^^^^^ > I'd suggest "If a handler returns" instead. There's just one > HANDLER involved here, right? Thanks, yes. >> +error handler continues from where it left off." > > This "from where it left off" sounds confusing: what does it mean? > IOW, how is it different from saying > > If a HANDLER returns normally, other CONDITIONS are searched for a > match, and, if found, their HANDLERs are called. > > Btw, this begs the question: what happens if none of the CONDITIONS > match? In particular, what happens if a HANDLER is called, returns > normally, and none of the other CONDITIONS match? Same as for `condition-case`, we keep searching in surrounding handlers. Not sure how to say it more clearly without becoming too verbose for a docstring. That's what the Texinfo doc is for, no? >> + ;; FIXME: Completion support as in `condition-case'? > ^^^^^ > What about this FIXME? Haven't implemented that yet. `handler-bind` is not going to be used nearly as often as `condition-case`, but I don't think it's very high priority to implement this feature. [ A more important completion feature in this area would be to complete the name of existing generic functions after `cl-defmethod` :-) ] >> @@ -317,6 +312,7 @@ call_debugger (Lisp_Object arg) >> /* Interrupting redisplay and resuming it later is not safe under >> all circumstances. So, when the debugger returns, abort the >> interrupted redisplay by going back to the top-level. */ >> + /* FIXME: Move this to the redisplay code? */ > ^^^^^ > And this one? That's the "redisplay_counter" patch we discussed elsewhere. I have it in the `scratch/handler-bind-2` branch, but it's not really related to `handler-bind`. >> +DEFUN ("handler-bind-1", Fhandler_bind_1, Shandler_bind_1, 1, MANY, 0, >> + doc: /* Setup error handlers around execution of BODYFUN. >> +BODYFUN be a function and it is called with no arguments. >> +CONDITIONS should be a list of condition names (symbols). >> +When an error is signaled during executon of BODYFUN, if that >> +error matches one of CONDITIONS, then the associated HANDLER is >> +called with the error as argument. >> +HANDLER should either transfer the control via a non-local exit, >> +or return normally. >> +If it returns normally, the search for an error handler continues >> +from where it left off. > "Where it left off" strikes again... Of course :-) >> + specpdl_ref count = SPECPDL_INDEX (); >> + max_ensure_room (20); >> + /* FIXME: 'handler-bind' makes `signal-hook-function' obsolete? */ >> + /* FIXME: Here we still "split" the error object >> + into its error-symbol and its error-data? */ >> call2 (Vsignal_hook_function, error_symbol, data); >> + unbind_to (count, Qnil); > > FIXMEs again. Yup. For the first, I'm not yet sure if it really makes `signal-hook-function` obsolete (I have PoC patches on `handler-bind-2` to remove existing uses, but I'm not sure these DTRT). For the second, it's an API problem we can't really fix without breaking backward compatibility. If we're lucky, we can declare `signal-hook-function` obsolete and those problems will disappear. >> top_level_2 (void) >> { >> - return Feval (Vtop_level, Qnil); >> + /* If we're in batch mode, print a backtrace unconditionally when >> + encountering an error, to help with debugging. */ >> + bool setup_handler = noninteractive; >> + if (setup_handler) >> + /* FIXME: Should we (re)use `list_of_error` from `xdisp.c`? */ >> + push_handler_bind (list1 (Qerror), Qdebug_early__handler, 0); > > And again. Here, I'm really asking reviewers whether they think we should use `list_of_error` here (which would require making it non-static and declaring it in `lisp.h` or somesuch). >> +;; (ert-deftest ert-test-fail-debug-with-condition-case () >> +;; (let ((test (make-ert-test :body (lambda () (ert-fail "failure message"))))) >> +;; (condition-case condition >> +;; (progn >> +;; (let ((ert-debug-on-error t)) >> +;; (ert-run-test test)) >> +;; (cl-assert nil)) >> +;; ((error) >> +;; (cl-assert (equal condition '(ert-test-failed "failure message")) t))))) > > What about this and other places where some code was commented-out, > but not removed? Those seem to be tests that you disable - why? The commit message explains it: Now that `ert.el` uses `handler-bind` instead of `debugger`, some details of the behavior have changed. More specifically, three tests are now broken, but these basically tested the failure of ERT's machinery to record errors when ERT was run within a `condition-case`. AFAICT, these tests do not check for a behavior that we want, so rather than "fix" them, I disabled them. Maybe I should delete them rather than comment them out? I guess I could also keep them commented out but with the above commit message turned into a comment, but in that case I have to move those 3 tests so they can be together next to the new comment. Either way works for me. > Last, but not least: do all the tests in the test suite pass after > these changes, both with and without native-compilation? Yup. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-30 7:50 ` Eli Zaretskii 2023-12-28 18:25 ` Ihor Radchenko 2023-12-30 7:52 ` Eli Zaretskii 2 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 18:14 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 > See patch below for my attempt to clarify. Sigh! Here it is, Stefan diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 4107963eed5..e63660206d0 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -2311,24 +2311,100 @@ Handling Errors @code{(@var{conditions} @var{handler})} where @var{conditions} is an error condition name to be handled, or a list of condition names, and @var{handler} should be a form whose evaluation should return a function. +As with @code{condition-case}, condition names are symbols. Before running @var{body}, @code{handler-bind} evaluates all the @var{handler} forms and installs those handlers to be active during -the evaluation of @var{body}. These handlers are searched together -with those installed by @code{condition-case}. When the innermost +the evaluation of @var{body}. When an error is signaled, +Emacs searches all the active @code{condition-case} and +@code{handler-bind} forms for a handler that +specifies one or more of these condition names. When the innermost matching handler is one installed by @code{handler-bind}, the @var{handler} function is called with a single argument holding the error description. -@var{handler} is called in the dynamic context where the error -happened, without first unwinding the stack, meaning that all the -dynamic bindings are still in effect, except that all the error -handlers between the code that signaled the error and the -@code{handler-bind} are temporarily suspended. Like any normal -function, @var{handler} can exit non-locally, typically via -@code{throw}, or it can return normally. If @var{handler} returns -normally, it means the handler @emph{declined} to handle the error and -the search for an error handler is continued where it left off. +Contrary to what happens with @code{condition-case}, @var{handler} is +called in the dynamic context where the error happened, without +unbinding any variable bindings or running any cleanups of +@code{unwind-protect}, so that all those dynamic bindings are still in +effect. There is one exception: while running the @var{handler} +function, all the error handlers between the code that signaled the +error and the @code{handler-bind} are temporarily suspended, meaning +that when an error is signaled, Emacs will only search the active +@code{condition-case} and @code{handler-bind} forms that are inside +the @var{handler} function or outside of the current +@code{handler-bind}. + +Like any normal function, @var{handler} can exit non-locally, +typically via @code{throw}, or it can return normally. +If @var{handler} returns normally, it means the handler +@emph{declined} to handle the error and the search for an error +handler is continued where it left off. + +For example, if we wanted to keep a log of all the errors that occur +during the execution of a particular piece of code together with the +buffer that's current when the error is signaled, but without +otherwise affecting the behavior of that code, we can do it with: + +@example +@group +(handler-bind + ((error + (lambda (err) + (push (cons err (current-buffer)) my-log-of-errors)))) + @var{body-forms}@dots{}) +@end group +@end example + +This will log only those errors that are not caught internally to +@var{body-forms}@dots{}, in other words errors that ``escape'' from +@var{body-forms}@dots{}, and it will not prevent those errors from +being passed on to surrounding @code{condition-case} handlers (or +@code{handler-bind} handlers for that matter) since the above handler +returns normally. + +We can also use @code{handler-bind} to replace an error with another, +as in the code below which turns all errors of type @code{user-error} +that occur during the execution of @var{body-forms}@dots{} into plain +@code{error}: + +@example +@group +(handler-bind + ((user-error + (lambda (err) + (signal 'error (cdr err))))) + @var{body-forms}@dots{}) +@end group +@end example + +We can get almost the same result with @code{condition-case}: + +@example +@group +(condition-case err + (progn @var{body-forms}@dots{}) + (user-error (signal 'error (cdr err)))) +@end group +@end example + +But with the difference that when we (re)signal the new error in +@code{handler-bind} the dynamic environment from the original error is +still active, which means for example that if we were to enter the +debugger at this point, it will show us a complete backtrace including +the point where we signaled the original error: + +@example +@group +Debugger entered--Lisp error: (error "Oops") + signal(error ("Oops")) + (closure (t) (err) (signal 'error (cdr err)))((user-error "Oops")) + user-error("Oops") + @dots{} + eval((handler-bind ((user-error (lambda (err) @dots{} +@end group +@end example + @end defmac @node Error Symbols diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index 45c892ad5a7..c3d980e1717 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -848,15 +848,17 @@ Eval @end defopt @defopt lisp-eval-depth-reserve -In order to be able to debug infinite recursion errors, Entry to the -Lisp debugger increases temporarily the value of +In order to be able to debug infinite recursion errors, when invoking the +Lisp debugger, Emacs increases temporarily the value of @code{max-lisp-eval-depth}, if there is little room left, to make sure the debugger itself has room to execute. The same happens when -running the handler of a @code{handler-bind}. +running the handler of a @code{handler-bind}. @xref{Handling Errors}. The variable @code{lisp-eval-depth-reserve} bounds the extra depth that Emacs can add to @code{max-lisp-eval-depth} for those exceptional circumstances. + +The default value of this variable is 200. @end defopt diff --git a/etc/NEWS b/etc/NEWS index 014c32b4d8e..e446f05190a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1371,6 +1371,7 @@ It puts a limit to the amount by which Emacs can temporarily increase Provides a functionality similar to `condition-case` except it runs the handler code without unwinding the stack, such that we can record the backtrace and other dynamic state at the point of the error. +See the Info node "(elisp) Handling Errors". +++ ** New 'pop-up-frames' action alist entry for 'display-buffer'. diff --git a/lisp/subr.el b/lisp/subr.el index 600b4d27f18..57e2473c2bb 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -7501,13 +7501,13 @@ handler-bind "Setup error HANDLERS around execution of BODY. HANDLERS is a list of (CONDITIONS HANDLER) where CONDITIONS should be a list of condition names (symbols) or -a single condition name and HANDLER is a form whose evaluation +a single condition name, and HANDLER is a form whose evaluation returns a function. When an error is signaled during execution of BODY, if that error matches CONDITIONS, then the associated HANDLER -function is called with the error as argument. +function is called with the error object as argument. HANDLERs can either transfer the control via a non-local exit, -or return normally. If they return normally the search for an +or return normally. If a handler returns normally, the search for an error handler continues from where it left off." ;; FIXME: Completion support as in `condition-case'? (declare (indent 1) (debug ((&rest (sexp form)) body))) ^ permalink raw reply related [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-30 7:50 ` Eli Zaretskii 0 siblings, 0 replies; 19+ messages in thread From: Eli Zaretskii @ 2023-12-30 7:50 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: 68075@debbugs.gnu.org > Date: Thu, 28 Dec 2023 13:14:25 -0500 > > +We can get almost the same result with @code{condition-case}: > + > +@example > +@group > +(condition-case err > + (progn @var{body-forms}@dots{}) > + (user-error (signal 'error (cdr err)))) > +@end group > +@end example > + > +But with the difference that when we (re)signal the new error in You want to start the above line with a lower-case "but", and you want a @noindent before it. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 18:25 ` Ihor Radchenko 2023-12-28 22:04 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-30 7:52 ` Eli Zaretskii 2 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2023-12-28 18:25 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, 68075 Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> writes: > I'm trying to explain that when looking for a handler, we look both for > condition-case handler and handler-bind handlers and we use whichever is > "closest", i.e. more deeply nested. So just like a local > `condition-case` overrides temporarily an outer one, the same holds not > only among `handler-bind`s but also between `condition-case` and > `handler-bind` as well. Then, it would also make sense to make `condition-case' and `handler-bind' refer to each other from the docstrings. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 18:25 ` Ihor Radchenko @ 2023-12-28 22:04 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-28 22:04 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Eli Zaretskii, 68075 >> I'm trying to explain that when looking for a handler, we look both for >> condition-case handler and handler-bind handlers and we use whichever is >> "closest", i.e. more deeply nested. So just like a local >> `condition-case` overrides temporarily an outer one, the same holds not >> only among `handler-bind`s but also between `condition-case` and >> `handler-bind` as well. > > Then, it would also make sense to make `condition-case' and > `handler-bind' refer to each other from the docstrings. BTW, `condition-case` can be implemented as a macro on top of `handler-bind` and `catch`, e.g. (condition-case ERR FORM (error HANDLER)) can become something like: (let* ((tag (cons nil nil)) (ERR (catch tag (handler-bind ((error (lambda (err) (throw tag err)))) (cons 'noerror FORM))))) (if (eq 'noerror (car ERR)) (cdr ERR) HANDLER)) :-) -- Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 18:25 ` Ihor Radchenko @ 2023-12-30 7:52 ` Eli Zaretskii 2023-12-31 19:07 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2023-12-30 7:52 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: 68075@debbugs.gnu.org > Date: Thu, 28 Dec 2023 13:12:12 -0500 > > >> +@var{handler} is called in the dynamic context where the error > >> +happened, without first unwinding the stack, meaning that all the > >> +dynamic bindings are still in effect, > > > > Should we tell something about the effects of lexical-binding on those > > "dynamic bindings"? > > It's not related to `handler-bind` in any case, so if > we want to say something about it, we should do it elsewhere (and > I think we already do when we discuss lexical binding). Maybe I'm confused by your use of "dynamic context" and "dynamic bindings" in that passage, which somehow hinted on dynamic vs lexical binding. If this is irrelevant, maybe try to reword the text so that this potentially confusing terminology is not used? Thanks. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-30 7:52 ` Eli Zaretskii @ 2023-12-31 19:07 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-31 19:36 ` Eli Zaretskii 0 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-31 19:07 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 >> >> +@var{handler} is called in the dynamic context where the error >> >> +happened, without first unwinding the stack, meaning that all the >> >> +dynamic bindings are still in effect, >> > >> > Should we tell something about the effects of lexical-binding on those >> > "dynamic bindings"? >> >> It's not related to `handler-bind` in any case, so if >> we want to say something about it, we should do it elsewhere (and >> I think we already do when we discuss lexical binding). > > Maybe I'm confused by your use of "dynamic context" and "dynamic > bindings" in that passage, which somehow hinted on dynamic vs lexical > binding. Of course: "dynamic context" refers to things that include dynamically bound variable (as well as the set of active catch tags, error handlers, and unwind-protect forms), and does not include statically bound variables. `handler-bind` is different from `condition-case` in the way it interacts with that dynamic context. But for statically bound variables, well, they obey the rules of static scoping so there's nothing to influence here. > If this is irrelevant, maybe try to reword the text so that > this potentially confusing terminology is not used? Could you give an example piece of code where this "confusing terminology" makes you unsure how things would work? Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-31 19:07 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-31 19:36 ` Eli Zaretskii 2024-01-01 15:37 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2023-12-31 19:36 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: 68075@debbugs.gnu.org > Date: Sun, 31 Dec 2023 14:07:18 -0500 > > >> >> +@var{handler} is called in the dynamic context where the error > >> >> +happened, without first unwinding the stack, meaning that all the > >> >> +dynamic bindings are still in effect, > >> > > >> > Should we tell something about the effects of lexical-binding on those > >> > "dynamic bindings"? > >> > >> It's not related to `handler-bind` in any case, so if > >> we want to say something about it, we should do it elsewhere (and > >> I think we already do when we discuss lexical binding). > > > > Maybe I'm confused by your use of "dynamic context" and "dynamic > > bindings" in that passage, which somehow hinted on dynamic vs lexical > > binding. > > Of course: "dynamic context" refers to things that include dynamically > bound variable (as well as the set of active catch tags, error handlers, > and unwind-protect forms), and does not include statically bound > variables. `handler-bind` is different from `condition-case` in the way > it interacts with that dynamic context. But for statically bound > variables, well, they obey the rules of static scoping so there's > nothing to influence here. > > > If this is irrelevant, maybe try to reword the text so that > > this potentially confusing terminology is not used? > > Could you give an example piece of code where this "confusing > terminology" makes you unsure how things would work? That's the quoted part of your patch at the beginning of this message. It uses the word "dynamic" twice and "dynamic bindings" once. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2023-12-31 19:36 ` Eli Zaretskii @ 2024-01-01 15:37 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-01 16:06 ` Eli Zaretskii 0 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-01 15:37 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 >> Could you give an example piece of code where this "confusing >> terminology" makes you unsure how things would work? > That's the quoted part of your patch at the beginning of this message. > It uses the word "dynamic" twice and "dynamic bindings" once. So, IIUC, reading that text makes you feel unsure, but you don't really know what you're unsure of? Not sure how to fix that. Should I just add a line that says that statically scoped variables are not affected? It feels kinda of odd/redundant to say that since by definition they're not "dynamic" (and also, any other behavior in this respect would be *very* weird since the handlers are clearly function *values* and thus could just as well be written/computed right *before* the `handler-bind`). More importantly I get the impression that it will still leave a lingering feeling that you're unsure about what other things could be affected (and how) or about what it means to be affected. For this reason it would help if you could try and characterize more precisely what you find confusing. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-01 15:37 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-01 16:06 ` Eli Zaretskii 2024-01-01 16:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2024-01-01 16:06 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: 68075@debbugs.gnu.org > Date: Mon, 01 Jan 2024 10:37:01 -0500 > > >> Could you give an example piece of code where this "confusing > >> terminology" makes you unsure how things would work? > > That's the quoted part of your patch at the beginning of this message. > > It uses the word "dynamic" twice and "dynamic bindings" once. > > So, IIUC, reading that text makes you feel unsure, but you don't really > know what you're unsure of? Oh, but I do: the two references to "dynamic", including one to "dynamic binding" seem to indicate quite unequivocally that "dynamic binding" vs "lexical binding" could be involved. I wonder why it is so hard to understand this difficulty, when the words basically speak for themselves. > For this reason it would help if you could try and characterize more > precisely what you find confusing. I don't have anything else to say except point once again to your wording, which I already did several times... ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-01 16:06 ` Eli Zaretskii @ 2024-01-01 16:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-01 17:35 ` Eli Zaretskii 0 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-01 16:55 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 >> So, IIUC, reading that text makes you feel unsure, but you don't really >> know what you're unsure of? > > Oh, but I do: the two references to "dynamic", including one to > "dynamic binding" seem to indicate quite unequivocally that "dynamic > binding" vs "lexical binding" could be involved. Yes, it is involved: statically scoped vars are not affected, while dynamically scoped vars are affected, which is why the text says "dynamic". > I wonder why it is so hard to understand this difficulty, when the > words basically speak for themselves. I guess I don't understand how "the words basically speak for themselves" leads to a difficulty. >> For this reason it would help if you could try and characterize more >> precisely what you find confusing. > I don't have anything else to say except point once again to your > wording, which I already did several times... Sadly, I still fail to grasp what kind of change to the wording could address the problem because I still don't really understand the problem. Maybe you could try to rewrite that bit in a way that you find more clear (or if there's still some part of the behavior over which you have doubts, then I'd be happily to try and explain it further). Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-01 16:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-01 17:35 ` Eli Zaretskii 2024-01-02 4:56 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2024-01-01 17:35 UTC (permalink / raw) To: Stefan Monnier; +Cc: 68075 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: 68075@debbugs.gnu.org > Date: Mon, 01 Jan 2024 11:55:43 -0500 > > >> So, IIUC, reading that text makes you feel unsure, but you don't really > >> know what you're unsure of? > > > > Oh, but I do: the two references to "dynamic", including one to > > "dynamic binding" seem to indicate quite unequivocally that "dynamic > > binding" vs "lexical binding" could be involved. > > Yes, it is involved: statically scoped vars are not affected, while > dynamically scoped vars are affected, which is why the text says > "dynamic". Ah, so lexical binding _is_ relevant to this, in the sense that lexically-bound variables are _not_ affected! Then please say that, maybe in parentheses or as a footnote. And please don't use "statically scoped", because we don't use this terminology anywhere in the ELisp manual. We always say "lexical scoping". > Sadly, I still fail to grasp what kind of change to the wording could > address the problem because I still don't really understand the problem. > Maybe you could try to rewrite that bit in a way that you find more > clear (or if there's still some part of the behavior over which you have > doubts, then I'd be happily to try and explain it further). I hope now it is more clear. ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-01 17:35 ` Eli Zaretskii @ 2024-01-02 4:56 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-04 23:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-05 0:50 ` Stefan Kangas 0 siblings, 2 replies; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-02 4:56 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075 >> >> So, IIUC, reading that text makes you feel unsure, but you don't really >> >> know what you're unsure of? >> > >> > Oh, but I do: the two references to "dynamic", including one to >> > "dynamic binding" seem to indicate quite unequivocally that "dynamic >> > binding" vs "lexical binding" could be involved. >> >> Yes, it is involved: statically scoped vars are not affected, while >> dynamically scoped vars are affected, which is why the text says >> "dynamic". > > Ah, so lexical binding _is_ relevant to this, in the sense that > lexically-bound variables are _not_ affected! Right, it's relevant to the extent that it's ... not relevant :-) > Then please say that, maybe in parentheses or as a footnote. OK. [ Tho I feel it is kind of silly, since as soon as you consider actual examples, it should become obvious that it has to be the case. ] > And please don't use "statically scoped", I use it in email messages, because I consider it to be the better term, from a technical point of view. But indeed, I don't use it in the docs, because it's too late to fix it there. >> Sadly, I still fail to grasp what kind of change to the wording could >> address the problem because I still don't really understand the problem. >> Maybe you could try to rewrite that bit in a way that you find more >> clear (or if there's still some part of the behavior over which you have >> doubts, then I'd be happily to try and explain it further). > > I hope now it is more clear. Kind of. I still don't understand how/why it helps you, but at least you say it does, which I guess is good enough. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-02 4:56 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-04 23:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-05 0:38 ` Stefan Kangas 2024-01-05 0:50 ` Stefan Kangas 1 sibling, 1 reply; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-04 23:57 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 68075-done Pushed to `master`, closing, Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-04 23:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-05 0:38 ` Stefan Kangas 0 siblings, 0 replies; 19+ messages in thread From: Stefan Kangas @ 2024-01-05 0:38 UTC (permalink / raw) To: Stefan Monnier, Eli Zaretskii; +Cc: 68075 Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> writes: > Pushed to `master`, closing, Thanks! ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-02 4:56 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-04 23:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-05 0:50 ` Stefan Kangas 2024-01-05 2:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 19+ messages in thread From: Stefan Kangas @ 2024-01-05 0:50 UTC (permalink / raw) To: Stefan Monnier, Eli Zaretskii; +Cc: 68075 Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> writes: >> And please don't use "statically scoped", > > I use it in email messages, because I consider it to be the better term, > from a technical point of view. But indeed, I don't use it in the docs, > because it's too late to fix it there. I'm thumbing through my Dragon book for other reasons and they say "static scope or lexical scope". The index item for "lexical scope" says "see static scope". We already have an index entry for "dynamic scope" in the elisp manual. Would it make sense to add an index item for "static scope" too? ^ permalink raw reply [flat|nested] 19+ messages in thread
* bug#68075: 30.0.50; New special form `handler-bind` 2024-01-05 0:50 ` Stefan Kangas @ 2024-01-05 2:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 19+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-01-05 2:57 UTC (permalink / raw) To: Stefan Kangas; +Cc: Eli Zaretskii, 68075 > We already have an index entry for "dynamic scope" in the elisp manual. > Would it make sense to add an index item for "static scope" too? % grep 'static scope' **/*.texi doc/lispref/variables.texi:@cindex static scope % 🙂 Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2024-01-05 2:57 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-12-28 6:33 bug#68075: 30.0.50; New special form `handler-bind` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 8:03 ` Eli Zaretskii 2023-12-28 18:12 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-28 18:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-30 7:50 ` Eli Zaretskii 2023-12-28 18:25 ` Ihor Radchenko 2023-12-28 22:04 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-30 7:52 ` Eli Zaretskii 2023-12-31 19:07 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-12-31 19:36 ` Eli Zaretskii 2024-01-01 15:37 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-01 16:06 ` Eli Zaretskii 2024-01-01 16:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-01 17:35 ` Eli Zaretskii 2024-01-02 4:56 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-04 23:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-01-05 0:38 ` Stefan Kangas 2024-01-05 0:50 ` Stefan Kangas 2024-01-05 2:57 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).