Package: emacs;
Reported by: npostavs <at> users.sourceforge.net
Date: Fri, 11 Nov 2016 03:11:02 UTC
Severity: wishlist
Tags: fixed, patch
Done: npostavs <at> users.sourceforge.net
Bug is archived. No further changes may be made.
Message #12 received at 24923 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: npostavs <at> users.sourceforge.net Cc: 24923 <at> debbugs.gnu.org Subject: Re: bug#24923: 25.1; Lisp watchpoints Date: Fri, 11 Nov 2016 12:02:42 +0200
> From: npostavs <at> users.sourceforge.net > Date: Thu, 10 Nov 2016 22:10:38 -0500 > > Continuing from > https://lists.nongnu.org/archive/html/emacs-devel/2015-11/msg01437.html, > main code difference since then is that I use a subr instead of indexing > into a table of C functions (the reason for using an index was to avoid > GC on Ffuncall; instead I did that by checking if the function is SUBRP > and doing funcall_subr on it (a new function extracted from Ffuncall)). Thanks. A few comments below. One general comment is that these patches are harder to review due to whitespace changes TAB->spaces. How about using some non-default options to "git diff" when generating the patch? > >From 0507854b885681c2e57bb1c6cb97f898417bd99c Mon Sep 17 00:00:00 2001 This changeset was attached twice, for some reason. > --- a/src/data.c > +++ b/src/data.c > @@ -649,9 +649,10 @@ DEFUN ("makunbound", Fmakunbound, Smakunbound, 1, 1, 0, > (register Lisp_Object symbol) > { > CHECK_SYMBOL (symbol); > - if (SYMBOL_CONSTANT_P (symbol)) > + if (XSYMBOL (symbol)->trapped_write == SYMBOL_NOWRITE) > xsignal1 (Qsetting_constant, symbol); > - Fset (symbol, Qunbound); > + else > + Fset (symbol, Qunbound); > return symbol; Why was this needed? Doesn't xsignal1 never return anymore? > +static void > +reset_symbol_trapped_write (Lisp_Object symbol) > +{ > + set_symbol_trapped_write (symbol, SYMBOL_TRAPPED_WRITE); > +} Suggest to find a better name for this function, like restore_symbol_trapped_write, for example. Calling an action that sets an attribute "reset" makes it harder to read the code. > +DEFUN ("add-variable-watcher", Fadd_variable_watcher, Sadd_variable_watcher, > + 2, 2, 0, > + doc: /* Cause WATCH-FUNCTION to be called when SYMBOL is set. */) I think the doc string needs to mention that the function also affects all of SYMBOL's aliases. > +DEFUN ("remove-variable-watcher", Fremove_variable_watcher, Sremove_variable_watcher, > + 2, 2, 0, > + doc: /* Undo the effect of `add-variable-watcher'. */) The doc string should mention SYMBOL. Also, preferably have the doc string be self-contained, since that's easy in this case. > + (Lisp_Object symbol, Lisp_Object watch_function) > +{ > + symbol = Findirect_variable (symbol); > + Lisp_Object watchers = Fget (symbol, Qwatchers); > + watchers = Fdelete (watch_function, watchers); > + if (NILP (watchers)) > + { > + set_symbol_trapped_write (symbol, SYMBOL_UNTRAPPED_WRITE); > + map_obarray (Vobarray, harmonize_variable_watchers, symbol); > + } > + Fput (symbol, Qwatchers, watchers); > + return Qnil; Would it be more useful for this and add-variable-watcher to return the list of watchers instead? > + /* Avoid recursion. */ > + set_symbol_trapped_write (symbol, SYMBOL_UNTRAPPED_WRITE); > + ptrdiff_t count = SPECPDL_INDEX (); > + record_unwind_protect (reset_symbol_trapped_write, symbol); I think record_unwind_protect should be called before setting the attribute, for this code to be safer and more future-proof. > +/* Value is non-zero if symbol cannot be changed through a simple set, > + i.e. it's a constant (e.g. nil, t, :keywords), or it has some > + watching functions. */ > > INLINE int > -(SYMBOL_CONSTANT_P) (Lisp_Object sym) > +(SYMBOL_TRAPPED_WRITE_P) (Lisp_Object sym) > { > - return lisp_h_SYMBOL_CONSTANT_P (sym); > + return lisp_h_SYMBOL_TRAPPED_WRITE_P (sym); > } > > /* Placeholder for make-docfile to process. The actual symbol > @@ -3289,6 +3299,12 @@ set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next) > XSYMBOL (sym)->next = next; > } > > +INLINE void > +make_symbol_constant (Lisp_Object sym) > +{ > + XSYMBOL (sym)->trapped_write = SYMBOL_NOWRITE; > +} > + So we will have make_symbol_constant, but no SYMBOL_CONSTANT_P? Isn't that confusing? Some C code may wish to know whether a symbol is constant, not just either constant or trap-on-write; why not give them what they want? > + ;; Watchpoint triggered. > + ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args))) > + (insert > + "--" > + (pcase details > + (`(makunbound ,_) (format "Making %s void" symbol)) > + (`(let ,_) (format "let-binding %s to %S" symbol newval)) > + (`(unlet ,_) (format "ending let-binding of %s" symbol)) > + (`(set nil) (format "setting %s to %S" symbol newval)) > + (`(set ,buffer) (format "setting %s in %s to %S" ^^^^^^^^^^^^^^^^^^^^^^^^ IMO, this should include the word "buffer", otherwise it can be confusing. > + (_ (format "watchpoint triggered %S" (cdr args)))) Can you give a couple of examples of this, with %S shown explicitly? I'm not sure whether the result will be self-explanatory. > +;;;###autoload > +(defun debug-watch (variable) > + (interactive > + (let* ((var-at-point (variable-at-point)) > + (var (and (symbolp var-at-point) var-at-point)) > + (val (completing-read > + (concat "Debug when setting variable" > + (if var (format " (default %s): " var) ": ")) I think all the other commands/variables similar to this one are named debug-on-SOMETHING, so perhaps this one should also have such a name. Like debug-on-setting-variable, perhaps? > +** New function `add-variable-watcher' can be used to execute code ^^^^^^^^^^^^^^^ It is better to say "to call a function" here. Thanks again for working on this.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.