From ef778f5143f04c6b5c0561ad38c04a08bb2cb701 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Fri, 26 May 2023 12:28:15 +0200 Subject: [PATCH] Add more function declarations * lisp/subr.el (buffer-narrowed-p, sha1, match-substitute-replacement) (version-to-list, version<, version<=, version=) (function-get, subregexp-context-p, split-string) (combine-and-quote-strings, split-string-and-unquote) (replace-regexp-in-string, syntax-after) (string-trim-left, string-trim): * lisp/emacs-lisp/subr-x.el (hash-table-empty-p, hash-table-keys) (hash-table-values, string-glyph-split) (string-clean-whitespace, string-fill, string-limit) (string-pixel-width): * lisp/env.el (substitute-env-vars, substitute-env-in-file-name) (setenv-internal): * lisp/emacs-lisp/rx.el (rx-to-string): * lisp/emacs-lisp/regexp-opt.el (regexp-opt-depth) (regexp-opt-charset): Add appropriate declarations: pure, side-effect-free, and/or important-return-value. --- lisp/emacs-lisp/regexp-opt.el | 2 ++ lisp/emacs-lisp/rx.el | 1 + lisp/emacs-lisp/subr-x.el | 9 +++++++++ lisp/env.el | 3 +++ lisp/subr.el | 18 +++++++++++++++++- 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/regexp-opt.el b/lisp/emacs-lisp/regexp-opt.el index fd9fbbe25a4..39325a3c35e 100644 --- a/lisp/emacs-lisp/regexp-opt.el +++ b/lisp/emacs-lisp/regexp-opt.el @@ -154,6 +154,7 @@ usually more efficient than that of a simplified version: "Return the depth of REGEXP. This means the number of non-shy regexp grouping constructs \(parenthesized expressions) in REGEXP." + (declare (pure t) (side-effect-free t)) (save-match-data ;; Hack to signal an error if REGEXP does not have balanced parentheses. (string-match regexp "") @@ -270,6 +271,7 @@ Merges keywords to avoid backtracking in Emacs's regexp matcher." CHARS should be a list of characters. If CHARS is the empty list, the return value is a regexp that never matches anything." + (declare (pure t) (side-effect-free t)) ;; The basic idea is to find character ranges. Also we take care in the ;; position of character set meta characters in the character set regexp. ;; diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 46f61c26bc4..e82490ffee5 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1144,6 +1144,7 @@ If NO-GROUP is non-nil, don't bracket the result in a non-capturing group. For extending the `rx' notation in FORM, use `rx-define' or `rx-let-eval'." + (declare (important-return-value t)) (let* ((item (rx--translate form)) (exprs (if no-group (car item) diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 947390b3de3..9e906930b92 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -81,18 +81,22 @@ Note how the single `-' got converted into a list before threading." (declare (indent 0) (debug thread-first)) `(internal--thread-argument nil ,@forms)) + (defsubst hash-table-empty-p (hash-table) "Check whether HASH-TABLE is empty (has 0 elements)." + (declare (side-effect-free t)) (zerop (hash-table-count hash-table))) (defsubst hash-table-keys (hash-table) "Return a list of keys in HASH-TABLE." + (declare (side-effect-free t)) (let ((keys nil)) (maphash (lambda (k _) (push k keys)) hash-table) keys)) (defsubst hash-table-values (hash-table) "Return a list of values in HASH-TABLE." + (declare (side-effect-free t)) (let ((values nil)) (maphash (lambda (_ v) (push v values)) hash-table) values)) @@ -149,6 +153,7 @@ carriage return." All sequences of whitespaces in STRING are collapsed into a single space character, and leading/trailing whitespace is removed." + (declare (important-return-value t)) (let ((blank "[[:blank:]\r\n]+")) (string-trim (replace-regexp-in-string blank " " string t t) blank blank))) @@ -158,6 +163,7 @@ removed." Wrapping is done where there is whitespace. If there are individual words in STRING that are longer than LENGTH, the result will have lines that are longer than LENGTH." + (declare (important-return-value t)) (with-temp-buffer (insert string) (goto-char (point-min)) @@ -189,6 +195,7 @@ coding system that doesn't specify a BOM, like `utf-16le' or `utf-16be'. When shortening strings for display purposes, `truncate-string-to-width' is almost always a better alternative than this function." + (declare (important-return-value t)) (unless (natnump length) (signal 'wrong-type-argument (list 'natnump length))) (if coding-system @@ -324,6 +331,7 @@ as the new values of the bound variables in the recursive invocation." ;;;###autoload (defun string-pixel-width (string) "Return the width of STRING in pixels." + (declare (important-return-value t)) (if (zerop (length string)) 0 ;; Keeping a work buffer around is more efficient than creating a @@ -344,6 +352,7 @@ This takes into account combining characters and grapheme clusters: if compositions are enabled, each sequence of characters composed on display into a single grapheme cluster is treated as a single indivisible unit." + (declare (side-effect-free t)) (let ((result nil) (start 0) comp) diff --git a/lisp/env.el b/lisp/env.el index faafcb6250f..281934af054 100644 --- a/lisp/env.el +++ b/lisp/env.el @@ -76,6 +76,7 @@ If it is non-nil and not a function, references to undefined variables are left unchanged. Use `$$' to insert a single dollar sign." + (declare (important-return-value t)) (let ((start 0)) (while (string-match env--substitute-vars-regexp string start) (cond ((match-beginning 1) @@ -94,6 +95,7 @@ Use `$$' to insert a single dollar sign." string)) (defun substitute-env-in-file-name (filename) + (declare (important-return-value t)) (substitute-env-vars filename ;; How 'bout we lookup other tables than the env? ;; E.g. we could accept bookmark names as well! @@ -104,6 +106,7 @@ Use `$$' to insert a single dollar sign." (defun setenv-internal (env variable value keep-empty) "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY. Changes ENV by side-effect, and returns its new value." + (declare (important-return-value t)) (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) (case-fold-search nil) (scan env) diff --git a/lisp/subr.el b/lisp/subr.el index 7670143c7cd..95d3bc03544 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4006,6 +4006,7 @@ See also `locate-user-emacs-file'.") (defsubst buffer-narrowed-p () "Return non-nil if the current buffer is narrowed." + (declare (side-effect-free t)) (/= (- (point-max) (point-min)) (buffer-size))) (defmacro with-restriction (start end &rest rest) @@ -4132,7 +4133,7 @@ See Info node `(elisp)Security Considerations'. If the optional POSIX argument is non-nil, ARGUMENT is quoted according to POSIX shell quoting rules, regardless of the system's shell." -(cond + (cond ((and (not posix) (eq system-type 'ms-dos)) ;; Quote using double quotes, but escape any existing quotes in ;; the argument with backslashes. @@ -4264,6 +4265,7 @@ string; otherwise returna 40-character string. Note that SHA-1 is not collision resistant and should not be used for anything security-related. See `secure-hash' for alternatives." + (declare (side-effect-free t)) (secure-hash 'sha1 object start end binary)) (defun function-get (f prop &optional autoload) @@ -4271,6 +4273,7 @@ alternatives." If AUTOLOAD is non-nil and F is autoloaded, try to load it in the hope that it will set PROP. If AUTOLOAD is `macro', do it only if it's an autoloaded macro." + (declare (important-return-value t)) (let ((val nil)) (while (and (symbolp f) (null (setq val (get f prop))) @@ -5226,6 +5229,7 @@ In other words, all back-references in the form `\\&' and `\\N' are substituted with actual strings matched by the last search. Optional FIXEDCASE, LITERAL, STRING and SUBEXP have the same meaning as for `replace-match'." + (declare (side-effect-free t)) (let ((match (match-string 0 string))) (save-match-data (match-data--translate (- (match-beginning 0))) @@ -5287,6 +5291,7 @@ A non-subregexp context is for example within brackets, or within a repetition bounds operator `\\=\\{...\\}', or right after a `\\'. If START is non-nil, it should be a position in REGEXP, smaller than POS, and known to be in a subregexp context." + (declare (important-return-value t)) ;; Here's one possible implementation, with the great benefit that it ;; reuses the regexp-matcher's own parser, so it understands all the ;; details of the syntax. A disadvantage is that it needs to match the @@ -5368,6 +5373,7 @@ case that you wish to retain zero-length substrings when splitting on whitespace, use `(split-string STRING split-string-default-separators)'. Modifies the match data; use `save-match-data' if necessary." + (declare (important-return-value t)) (let* ((keep-nulls (not (if separators omit-nulls t))) (rexp (or separators split-string-default-separators)) (start 0) @@ -5425,6 +5431,7 @@ Only some SEPARATORs will work properly. Note that this is not intended to protect STRINGS from interpretation by shells, use `shell-quote-argument' for that." + (declare (important-return-value t)) (let* ((sep (or separator " ")) (re (concat "[\\\"]" "\\|" (regexp-quote sep)))) (mapconcat @@ -5439,6 +5446,7 @@ interpretation by shells, use `shell-quote-argument' for that." It understands Emacs Lisp quoting within STRING, such that (split-string-and-unquote (combine-and-quote-strings strs)) == strs The SEPARATOR regexp defaults to \"\\s-+\"." + (declare (important-return-value t)) (let ((sep (or separator "\\s-+")) (i (string-search "\"" string))) (if (null i) @@ -5506,6 +5514,7 @@ To replace only the first match (if any), make REGEXP match up to \\\\=' and replace a sub-expression, e.g. (replace-regexp-in-string \"\\\\(foo\\\\).*\\\\\\='\" \"bar\" \" foo foo\" nil nil 1) => \" bar foo\"" + (declare (important-return-value t)) ;; To avoid excessive consing from multiple matches in long strings, ;; don't just call `replace-match' continually. Walk down the @@ -5861,6 +5870,7 @@ from `standard-syntax-table' otherwise." (defun syntax-after (pos) "Return the raw syntax descriptor for the char after POS. If POS is outside the buffer's accessible portion, return nil." + (declare (important-return-value t)) (unless (or (< pos (point-min)) (>= pos (point-max))) (let ((st (if parse-sexp-lookup-properties (get-char-property pos 'syntax-table)))) @@ -6675,6 +6685,7 @@ Examples of version conversion: \"22.8beta3\" (22 8 -2 3) See documentation for `version-separator' and `version-regexp-alist'." + (declare (side-effect-free t)) (unless (stringp ver) (error "Version must be a string")) ;; Change .x.y to 0.x.y @@ -6805,6 +6816,7 @@ etc. That is, the trailing \".0\"s are insignificant. Also, version string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\", which is higher than \"1alpha\", which is higher than \"1snapshot\". Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions." + (declare (side-effect-free t)) (version-list-< (version-to-list v1) (version-to-list v2))) (defun version<= (v1 v2) @@ -6815,6 +6827,7 @@ etc. That is, the trailing \".0\"s are insignificant. Also, version string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\", which is higher than \"1alpha\", which is higher than \"1snapshot\". Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions." + (declare (side-effect-free t)) (version-list-<= (version-to-list v1) (version-to-list v2))) (defun version= (v1 v2) @@ -6825,6 +6838,7 @@ etc. That is, the trailing \".0\"s are insignificant. Also, version string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\", which is higher than \"1alpha\", which is higher than \"1snapshot\". Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions." + (declare (side-effect-free t)) (version-list-= (version-to-list v1) (version-to-list v2))) (defvar package--builtin-versions @@ -6947,6 +6961,7 @@ returned list are in the same order as in TREE. "Trim STRING of leading string matching REGEXP. REGEXP defaults to \"[ \\t\\n\\r]+\"." + (declare (important-return-value t)) (if (string-match (if regexp (concat "\\`\\(?:" regexp "\\)") "\\`[ \t\n\r]+") @@ -6969,6 +6984,7 @@ REGEXP defaults to \"[ \\t\\n\\r]+\"." "Trim STRING of leading and trailing strings matching TRIM-LEFT and TRIM-RIGHT. TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"." + (declare (important-return-value t)) (string-trim-left (string-trim-right string trim-right) trim-left)) ;; The initial anchoring is for better performance in searching matches. -- 2.39.2