all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: emacs-devel@gnu.org
Subject: Lisp primitives and their calling of the change hooks
Date: Wed, 3 Jan 2018 12:45:43 +0000	[thread overview]
Message-ID: <20180103124543.GA5435@ACM> (raw)

Hello, Emacs.

I've just had an interesting few days investigating our privitives'
calling of before-change-functions and after-change-functions.

In an ideal world, each primitive would call each of those hooks exactly
once.  However, we're not in an ideal world, and there are primitives
which perform several (or many) distinct changes (e.g. transpose-regions
or subst-char-in-region) where a single pair of hook calls wouldn't make
sense.

TL;DR: There are several, but not many, primitives where
before-change-functions doesn't match after-change-functions.

Here is how I went about this:
1. Extract a list of external functions in insdel.c from the section in
lisp.h which declares them.  Form a regexp from this list, and convert it
into a grep regexp (by replacing '?' by '\?'.

2. grep -l *.c with this regexp.  This gave these files:
    buffer.c
    callproc.c
    casefiddle.c
    cmds.c
    coding.c
    decompress.c
    editfns.c
    emacs.c
    fileio.c
    fns.c
    indent.c
    insdel.c
    print.c
    process.c
    search.c
    textprop.c
    xdisp.c
    xml.c

3. Using GNU cflow, a utility which creates call graphs for C files,
create a reverse call graph (i.e. an "is called by" graph) for the 18 C
files.

4. Analyse this graph with an elisp script to find all functions which,
directly or indirectly, call signal_before_change or signal_after_change.

5. Filter this list of functions to leave only the lisp primitives (i.e.
functions starting with "F"), and convert to Lisp names.  Edit this list
by hand to remove those primitives which don't change the buffer (most of
them were removed).  This left the following list:
    (add-face-text-property)
    (add-text-properties)
    (base64-decode-region)
    (base64-encode-region)
    (capitalize-region)

    (capitalize-word)
    (delete-and-extract-region)
    (delete-char)
    (delete-field)
    (delete-region)

    (downcase-region)
    (downcase-word)
    (erase-buffer)
    (indent-to)
    (insert)

    (insert-and-inherit)
    (insert-before-markers)
    (insert-buffer-substring)
    (insert-byte)
    (insert-char)

    (insert-file-contents)
    (move-to-column)
    (princ)
    (print)
    (put-text-property)

    (remove-list-of-text-properties)
    (remove-text-properties)
    (replace-buffer-contents)
    (replace-match)
    (self-insert-command)

    (set-buffer-multibyte)
    (set-text-properties)
    (subst-char-in-region)
    (terpri)
    (translate-region-internal)

    (transpose-regions)
    (upcase-initials-region)
    (upcase-region)
    (upcase-word)
    (write-char)

    (zlib-decompress-region)

6. Write and run a script which executes each of these primitives whilst
counting the number of times it invokes before-change-hooks and
after-change-hooks.  Output messages where these numbers aren't 1 and 1.
This gave the following:
    Primitive              b-c-f calls         a-c-f calls
base64-encode-region          2                    2
base64-decode-region          2                    1
insert-file-contents          2                    2
move-to-column-1              3                    3   ; with the &optional
                                                       ; which untabifies.
replace-buffer-contents      123                  123
set-buffer-multibyte          0                    0   ; May have done nothing
tranlate-region-internal      1                   146
tranpose-regions              2                    1
upcase-initials-region        1                    0[*]
upcase-region                 1                    0[*]
zlib-decompress-region        0                    0
erase-buffer                  0                    0

[*] In upcase-... there weren't any lower case characters in the buffer
at the time.

This list is incomplete.  There were one or two other primitives which
triggered messages which I didn't write down, and now cannot reproduce.

7. Surpising is that insert-file-contents (which gave so much trouble in
summer 2016) returned balanced counts.  It seems to be mostly the special
purpose primitives, those not widely used in Lisp, which are most likely
to have strange b-c-f and a-c-f counts.  But the case-switching
primitives might be troublesome.  So might transpose-regions.

8. Possibly these things could be more accurately documented in
elisp.info.

-- 
Alan Mackenzie (Nuremberg, Germany).



             reply	other threads:[~2018-01-03 12:45 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-03 12:45 Alan Mackenzie [this message]
2018-01-03 21:51 ` Lisp primitives and their calling of the change hooks Stefan Monnier
2018-01-04 15:51   ` Alan Mackenzie
2018-01-04 18:16     ` Stefan Monnier
2018-01-04 21:11       ` Alan Mackenzie
2018-01-04 21:36         ` Stefan Monnier
2018-01-06 15:18           ` Alan Mackenzie
2018-01-06 15:51             ` Stefan Monnier
2018-01-06 16:18               ` Eli Zaretskii
2018-01-06 19:06                 ` Alan Mackenzie
2018-01-06 20:24               ` Alan Mackenzie
2018-01-07 11:36                 ` Alan Mackenzie
2018-01-07 11:49                   ` Eli Zaretskii
2018-01-07 12:08                     ` Alan Mackenzie
2018-01-07 13:56                       ` Alan Mackenzie
2018-01-07 15:21                         ` [SUSPECTED SPAM] " Stefan Monnier
2018-01-07 16:47                         ` Eli Zaretskii
2018-01-07 17:50                           ` Stefan Monnier
2018-01-07 17:58                             ` Eli Zaretskii
2018-01-07 19:04                               ` Stefan Monnier
2018-01-07 19:48                                 ` Alan Mackenzie
2018-01-07 19:58                                   ` Eli Zaretskii
2018-01-07 21:10                                     ` Alan Mackenzie
2018-01-08  3:41                                       ` Eli Zaretskii
2018-01-08 19:24                                         ` Alan Mackenzie
2018-01-08 21:15                                           ` Eli Zaretskii
2018-01-08 22:24                                             ` Stefan Monnier
2018-01-09  3:55                                               ` Eli Zaretskii
2018-01-09 13:30                                                 ` Stefan Monnier
2018-01-09 18:50                                                   ` Eli Zaretskii
2018-01-09 19:53                                             ` Alan Mackenzie
2018-01-09 20:05                                               ` Eli Zaretskii
2018-01-10 18:29                                                 ` Alan Mackenzie
2018-01-12 16:40                                                   ` Alan Mackenzie
2018-01-09 20:07                                               ` Stefan Monnier
2018-01-10 18:45                                                 ` Alan Mackenzie
2018-01-10 19:30                                                   ` Stefan Monnier
2018-01-10 19:48                                                     ` Alan Mackenzie
2018-01-10 20:33                                                       ` Stefan Monnier
2018-01-10 21:03                                                         ` Alan Mackenzie
2018-01-11 13:36                                                           ` Stefan Monnier
2018-01-11 17:39                                                             ` Alan Mackenzie
2018-01-11 19:35                                                               ` Stefan Monnier
2018-01-11 19:46                                                                 ` Alan Mackenzie
2018-01-11 20:15                                                                   ` Stefan Monnier
2018-01-11 21:20                                                                     ` Alan Mackenzie
2018-01-11 23:42                                                                       ` Stefan Monnier
2018-01-12 16:14                                                                         ` Alan Mackenzie
2018-01-10 22:06                                                       ` Clément Pit-Claudel
2018-01-10 22:20                                                         ` Alan Mackenzie
2018-01-08  4:29                                   ` Stefan Monnier
2018-01-07 17:54                           ` Alan Mackenzie
2018-01-07 18:05                             ` Eli Zaretskii
2018-01-05  6:55         ` Eli Zaretskii
2018-01-05 11:41           ` Alan Mackenzie
2018-01-05 13:00             ` Eli Zaretskii
2018-01-05 13:34               ` Alan Mackenzie
2018-01-05 14:08                 ` Eli Zaretskii
2018-01-05 15:54                   ` Alan Mackenzie
2018-01-05 16:50           ` Stefan Monnier
2018-01-05 17:38             ` Alan Mackenzie
2018-01-05 18:09               ` Stefan Monnier
2018-01-05 19:53             ` Eli Zaretskii
2018-01-05 22:28               ` Stefan Monnier
2018-01-06  9:05                 ` Eli Zaretskii
2018-01-06 15:26                   ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180103124543.GA5435@ACM \
    --to=acm@muc.de \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.