diff options
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/byte-opt.el | 3 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 18 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cconv.el | 38 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-preloaded.el | 15 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-print.el | 32 | ||||
| -rw-r--r-- | lisp/emacs-lisp/comp-common.el | 2 | ||||
| -rw-r--r-- | lisp/emacs-lisp/disass.el | 6 | ||||
| -rw-r--r-- | lisp/emacs-lisp/edebug.el | 2 | ||||
| -rw-r--r-- | lisp/emacs-lisp/lisp-mode.el | 1 | ||||
| -rw-r--r-- | lisp/emacs-lisp/nadvice.el | 6 | ||||
| -rw-r--r-- | lisp/emacs-lisp/oclosure.el | 96 | ||||
| -rw-r--r-- | lisp/help.el | 3 | ||||
| -rw-r--r-- | lisp/profiler.el | 5 | ||||
| -rw-r--r-- | lisp/simple.el | 5 |
14 files changed, 133 insertions, 99 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index ea163723a3e..3d6b35422b8 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -164,7 +164,7 @@ Earlier variables shadow later ones with the same name.") | |||
| 164 | ;; The byte-code will be really inlined in byte-compile-unfold-bcf. | 164 | ;; The byte-code will be really inlined in byte-compile-unfold-bcf. |
| 165 | (byte-compile--check-arity-bytecode form fn) | 165 | (byte-compile--check-arity-bytecode form fn) |
| 166 | `(,fn ,@(cdr form))) | 166 | `(,fn ,@(cdr form))) |
| 167 | ((or `(lambda . ,_) `(closure . ,_)) | 167 | ((pred interpreted-function-p) |
| 168 | ;; While byte-compile-unfold-bcf can inline dynbind byte-code into | 168 | ;; While byte-compile-unfold-bcf can inline dynbind byte-code into |
| 169 | ;; letbind byte-code (or any other combination for that matter), we | 169 | ;; letbind byte-code (or any other combination for that matter), we |
| 170 | ;; can only inline dynbind source into dynbind source or lexbind | 170 | ;; can only inline dynbind source into dynbind source or lexbind |
| @@ -1870,6 +1870,7 @@ See Info node `(elisp) Integer Basics'." | |||
| 1870 | charsetp | 1870 | charsetp |
| 1871 | ;; data.c | 1871 | ;; data.c |
| 1872 | arrayp atom bare-symbol-p bool-vector-p bufferp byte-code-function-p | 1872 | arrayp atom bare-symbol-p bool-vector-p bufferp byte-code-function-p |
| 1873 | interpreted-function-p closurep | ||
| 1873 | byteorder car-safe cdr-safe char-or-string-p char-table-p | 1874 | byteorder car-safe cdr-safe char-or-string-p char-table-p |
| 1874 | condition-variable-p consp eq floatp indirect-function | 1875 | condition-variable-p consp eq floatp indirect-function |
| 1875 | integer-or-marker-p integerp keywordp listp markerp | 1876 | integer-or-marker-p integerp keywordp listp markerp |
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index fb3278c08ab..59aa9098768 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -2900,9 +2900,14 @@ otherwise, print without quoting." | |||
| 2900 | (defun byte-compile--reify-function (fun) | 2900 | (defun byte-compile--reify-function (fun) |
| 2901 | "Return an expression which will evaluate to a function value FUN. | 2901 | "Return an expression which will evaluate to a function value FUN. |
| 2902 | FUN should be an interpreted closure." | 2902 | FUN should be an interpreted closure." |
| 2903 | (pcase-let* ((`(closure ,env ,args . ,body) fun) | 2903 | (let* ((args (aref fun 0)) |
| 2904 | (`(,preamble . ,body) (macroexp-parse-body body)) | 2904 | (body (aref fun 1)) |
| 2905 | (renv ())) | 2905 | (env (aref fun 2)) |
| 2906 | (docstring (function-documentation fun)) | ||
| 2907 | (iform (interactive-form fun)) | ||
| 2908 | (preamble `(,@(if docstring (list docstring)) | ||
| 2909 | ,@(if iform (list iform)))) | ||
| 2910 | (renv ())) | ||
| 2906 | ;; Turn the function's closed vars (if any) into local let bindings. | 2911 | ;; Turn the function's closed vars (if any) into local let bindings. |
| 2907 | (dolist (binding env) | 2912 | (dolist (binding env) |
| 2908 | (cond | 2913 | (cond |
| @@ -2939,11 +2944,11 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2939 | (if (symbolp form) form "provided")) | 2944 | (if (symbolp form) form "provided")) |
| 2940 | fun) | 2945 | fun) |
| 2941 | (t | 2946 | (t |
| 2942 | (when (or (symbolp form) (eq (car-safe fun) 'closure)) | 2947 | (when (or (symbolp form) (interpreted-function-p fun)) |
| 2943 | ;; `fun' is a function *value*, so try to recover its | 2948 | ;; `fun' is a function *value*, so try to recover its |
| 2944 | ;; corresponding source code. | 2949 | ;; corresponding source code. |
| 2945 | (when (setq lexical-binding (eq (car-safe fun) 'closure)) | 2950 | (setq lexical-binding (not (null (aref fun 2)))) |
| 2946 | (setq fun (byte-compile--reify-function fun))) | 2951 | (setq fun (byte-compile--reify-function fun)) |
| 2947 | (setq need-a-value t)) | 2952 | (setq need-a-value t)) |
| 2948 | ;; Expand macros. | 2953 | ;; Expand macros. |
| 2949 | (setq fun (byte-compile-preprocess fun)) | 2954 | (setq fun (byte-compile-preprocess fun)) |
| @@ -5133,7 +5138,6 @@ binding slots have been popped." | |||
| 5133 | ;; `arglist' is the list of arguments (or t if not recognized). | 5138 | ;; `arglist' is the list of arguments (or t if not recognized). |
| 5134 | ;; `body' is the body of `lam' (or t if not recognized). | 5139 | ;; `body' is the body of `lam' (or t if not recognized). |
| 5135 | ((or `(lambda ,arglist . ,body) | 5140 | ((or `(lambda ,arglist . ,body) |
| 5136 | ;; `(closure ,_ ,arglist . ,body) | ||
| 5137 | (and `(internal-make-closure ,arglist . ,_) (let body t)) | 5141 | (and `(internal-make-closure ,arglist . ,_) (let body t)) |
| 5138 | (and (let arglist t) (let body t))) | 5142 | (and (let arglist t) (let body t))) |
| 5139 | lam)) | 5143 | lam)) |
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 4ff47971351..e6a78f07762 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el | |||
| @@ -902,7 +902,7 @@ lexically and dynamically bound symbols actually used by FORM." | |||
| 902 | (delete-dups cconv--dynbindings))))) | 902 | (delete-dups cconv--dynbindings))))) |
| 903 | (cons fvs dyns))))) | 903 | (cons fvs dyns))))) |
| 904 | 904 | ||
| 905 | (defun cconv-make-interpreted-closure (fun env) | 905 | (defun cconv-make-interpreted-closure (args body env docstring iform) |
| 906 | "Make a closure for the interpreter. | 906 | "Make a closure for the interpreter. |
| 907 | This is intended to be called at runtime by the ELisp interpreter (when | 907 | This is intended to be called at runtime by the ELisp interpreter (when |
| 908 | the code has not been compiled). | 908 | the code has not been compiled). |
| @@ -911,22 +911,27 @@ ENV is the runtime representation of the lexical environment, | |||
| 911 | i.e. a list whose elements can be either plain symbols (which indicate | 911 | i.e. a list whose elements can be either plain symbols (which indicate |
| 912 | that this symbol should use dynamic scoping) or pairs (SYMBOL . VALUE) | 912 | that this symbol should use dynamic scoping) or pairs (SYMBOL . VALUE) |
| 913 | for the lexical bindings." | 913 | for the lexical bindings." |
| 914 | (cl-assert (eq (car-safe fun) 'lambda)) | 914 | (cl-assert (consp body)) |
| 915 | (cl-assert (listp args)) | ||
| 915 | (let ((lexvars (delq nil (mapcar #'car-safe env)))) | 916 | (let ((lexvars (delq nil (mapcar #'car-safe env)))) |
| 916 | (if (or (null lexvars) | 917 | (if (or |
| 917 | ;; Functions with a `:closure-dont-trim-context' marker | 918 | ;; Functions with a `:closure-dont-trim-context' marker |
| 918 | ;; should keep their whole context untrimmed (bug#59213). | 919 | ;; should keep their whole context untrimmed (bug#59213). |
| 919 | (and (eq :closure-dont-trim-context (nth 2 fun)) | 920 | (and (eq :closure-dont-trim-context (car body)) |
| 920 | ;; Check the function doesn't just return the magic keyword. | 921 | ;; Check the function doesn't just return the magic keyword. |
| 921 | (nthcdr 3 fun))) | 922 | (cdr body) |
| 923 | ;; Drop the magic marker from the closure. | ||
| 924 | (setq body (cdr body))) | ||
| 925 | ;; There's no var to capture, so skip the analysis. | ||
| 926 | (null lexvars)) | ||
| 922 | ;; The lexical environment is empty, or needs to be preserved, | 927 | ;; The lexical environment is empty, or needs to be preserved, |
| 923 | ;; so there's no need to look for free variables. | 928 | ;; so there's no need to look for free variables. |
| 924 | ;; Attempting to replace ,(cdr fun) by a macroexpanded version | 929 | ;; Attempting to replace body by a macroexpanded version |
| 925 | ;; causes bootstrap to fail. | 930 | ;; caused bootstrap to fail. |
| 926 | `(closure ,env . ,(cdr fun)) | 931 | (make-interpreted-closure args body env docstring iform) |
| 927 | ;; We could try and cache the result of the macroexpansion and | 932 | ;; We could try and cache the result of the macroexpansion and |
| 928 | ;; `cconv-fv' analysis. Not sure it's worth the trouble. | 933 | ;; `cconv-fv' analysis. Not sure it's worth the trouble. |
| 929 | (let* ((form `#',fun) | 934 | (let* ((form `#'(lambda ,args ,iform . ,body)) |
| 930 | (expanded-form | 935 | (expanded-form |
| 931 | (let ((lexical-binding t) ;; Tell macros which dialect is in use. | 936 | (let ((lexical-binding t) ;; Tell macros which dialect is in use. |
| 932 | ;; Make the macro aware of any defvar declarations in scope. | 937 | ;; Make the macro aware of any defvar declarations in scope. |
| @@ -935,10 +940,10 @@ for the lexical bindings." | |||
| 935 | (append env macroexp--dynvars) env))) | 940 | (append env macroexp--dynvars) env))) |
| 936 | (macroexpand-all form macroexpand-all-environment))) | 941 | (macroexpand-all form macroexpand-all-environment))) |
| 937 | ;; Since we macroexpanded the body, we may as well use that. | 942 | ;; Since we macroexpanded the body, we may as well use that. |
| 938 | (expanded-fun-cdr | 943 | (expanded-fun-body |
| 939 | (pcase expanded-form | 944 | (pcase expanded-form |
| 940 | (`#'(lambda . ,cdr) cdr) | 945 | (`#'(lambda ,_args ,_iform . ,newbody) newbody) |
| 941 | (_ (cdr fun)))) | 946 | (_ body))) |
| 942 | 947 | ||
| 943 | (dynvars (delq nil (mapcar (lambda (b) (if (symbolp b) b)) env))) | 948 | (dynvars (delq nil (mapcar (lambda (b) (if (symbolp b) b)) env))) |
| 944 | (fvs (cconv-fv expanded-form lexvars dynvars)) | 949 | (fvs (cconv-fv expanded-form lexvars dynvars)) |
| @@ -946,7 +951,8 @@ for the lexical bindings." | |||
| 946 | (cdr fvs)))) | 951 | (cdr fvs)))) |
| 947 | ;; Never return a nil env, since nil means to use the dynbind | 952 | ;; Never return a nil env, since nil means to use the dynbind |
| 948 | ;; dialect of ELisp. | 953 | ;; dialect of ELisp. |
| 949 | `(closure ,(or newenv '(t)) . ,expanded-fun-cdr))))) | 954 | (make-interpreted-closure args expanded-fun-body (or newenv '(t)) |
| 955 | docstring iform))))) | ||
| 950 | 956 | ||
| 951 | 957 | ||
| 952 | (provide 'cconv) | 958 | (provide 'cconv) |
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el index 83d9e6ee220..fa745396b02 100644 --- a/lisp/emacs-lisp/cl-preloaded.el +++ b/lisp/emacs-lisp/cl-preloaded.el | |||
| @@ -444,13 +444,24 @@ For this build of Emacs it's %dbit." | |||
| 444 | ) | 444 | ) |
| 445 | (cl--define-built-in-type compiled-function (function) | 445 | (cl--define-built-in-type compiled-function (function) |
| 446 | "Abstract type of functions that have been compiled.") | 446 | "Abstract type of functions that have been compiled.") |
| 447 | (cl--define-built-in-type byte-code-function (compiled-function) | 447 | (cl--define-built-in-type closure (function) |
| 448 | "Abstract type of functions represented by a vector-like object. | ||
| 449 | You can access the object's internals with `aref'. | ||
| 450 | The fields are used as follows: | ||
| 451 | |||
| 452 | 0 [args] Argument list (either a list or an integer) | ||
| 453 | 1 [code] Either a byte-code string or a list of Lisp forms | ||
| 454 | 2 [constants] Either vector of constants or a lexical environment | ||
| 455 | 3 [stackdepth] Maximum amount of stack depth used by the byte-code | ||
| 456 | 4 [docstring] The documentation, or a reference to it | ||
| 457 | 5 [iform] The interactive form (if present)") | ||
| 458 | (cl--define-built-in-type byte-code-function (compiled-function closure) | ||
| 448 | "Type of functions that have been byte-compiled.") | 459 | "Type of functions that have been byte-compiled.") |
| 449 | (cl--define-built-in-type subr (atom) | 460 | (cl--define-built-in-type subr (atom) |
| 450 | "Abstract type of functions compiled to machine code.") | 461 | "Abstract type of functions compiled to machine code.") |
| 451 | (cl--define-built-in-type module-function (function) | 462 | (cl--define-built-in-type module-function (function) |
| 452 | "Type of functions provided via the module API.") | 463 | "Type of functions provided via the module API.") |
| 453 | (cl--define-built-in-type interpreted-function (function) | 464 | (cl--define-built-in-type interpreted-function (closure) |
| 454 | "Type of functions that have not been compiled.") | 465 | "Type of functions that have not been compiled.") |
| 455 | (cl--define-built-in-type special-form (subr) | 466 | (cl--define-built-in-type special-form (subr) |
| 456 | "Type of the core syntactic elements of the Emacs Lisp language.") | 467 | "Type of the core syntactic elements of the Emacs Lisp language.") |
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index 5e5eee1da9e..3a8f80f6e93 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el | |||
| @@ -237,6 +237,38 @@ into a button whose action shows the function's disassembly.") | |||
| 237 | 'byte-code-function object))))) | 237 | 'byte-code-function object))))) |
| 238 | (princ ")" stream))) | 238 | (princ ")" stream))) |
| 239 | 239 | ||
| 240 | (cl-defmethod cl-print-object ((object interpreted-function) stream) | ||
| 241 | (unless stream (setq stream standard-output)) | ||
| 242 | (princ "#f(lambda " stream) | ||
| 243 | (let ((args (help-function-arglist object 'preserve-names))) | ||
| 244 | ;; It's tempting to print the arglist from the "usage" info in the | ||
| 245 | ;; doc (e.g. for `&key` args), but that only makes sense if we | ||
| 246 | ;; *don't* print the body, since otherwise the body will tend to | ||
| 247 | ;; refer to args that don't appear in the arglist. | ||
| 248 | (if args | ||
| 249 | (prin1 args stream) | ||
| 250 | (princ "()" stream))) | ||
| 251 | (let ((env (aref object 2))) | ||
| 252 | (if (null env) | ||
| 253 | (princ " :dynbind" stream) | ||
| 254 | (princ " " stream) | ||
| 255 | (cl-print-object | ||
| 256 | (vconcat (mapcar (lambda (x) (if (consp x) (list (car x) (cdr x)) x)) | ||
| 257 | env)) | ||
| 258 | stream))) | ||
| 259 | (let* ((doc (documentation object 'raw))) | ||
| 260 | (when doc | ||
| 261 | (princ " " stream) | ||
| 262 | (prin1 doc stream))) | ||
| 263 | (let ((inter (interactive-form object))) | ||
| 264 | (when inter | ||
| 265 | (princ " " stream) | ||
| 266 | (cl-print-object inter stream))) | ||
| 267 | (dolist (exp (aref object 1)) | ||
| 268 | (princ " " stream) | ||
| 269 | (cl-print-object exp stream)) | ||
| 270 | (princ ")" stream)) | ||
| 271 | |||
| 240 | ;; This belongs in oclosure.el, of course, but some load-ordering issues make it | 272 | ;; This belongs in oclosure.el, of course, but some load-ordering issues make it |
| 241 | ;; complicated. | 273 | ;; complicated. |
| 242 | (cl-defmethod cl-print-object ((object accessor) stream) | 274 | (cl-defmethod cl-print-object ((object accessor) stream) |
diff --git a/lisp/emacs-lisp/comp-common.el b/lisp/emacs-lisp/comp-common.el index 4edfe811586..62fd28f772e 100644 --- a/lisp/emacs-lisp/comp-common.el +++ b/lisp/emacs-lisp/comp-common.el | |||
| @@ -118,7 +118,9 @@ Used to modify the compiler environment." | |||
| 118 | (buffer-substring | 118 | (buffer-substring |
| 119 | (function ((or integer marker) (or integer marker)) string)) | 119 | (function ((or integer marker) (or integer marker)) string)) |
| 120 | (bufferp (function (t) boolean)) | 120 | (bufferp (function (t) boolean)) |
| 121 | (closurep (function (t) boolean)) | ||
| 121 | (byte-code-function-p (function (t) boolean)) | 122 | (byte-code-function-p (function (t) boolean)) |
| 123 | (interpreted-function-p (function (t) boolean)) | ||
| 122 | (capitalize (function ((or integer string)) (or integer string))) | 124 | (capitalize (function ((or integer string)) (or integer string))) |
| 123 | (car (function (list) t)) | 125 | (car (function (list) t)) |
| 124 | (car-less-than-car (function (list list) boolean)) | 126 | (car-less-than-car (function (list list) boolean)) |
diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el index 850cc2085f7..15caee9b29c 100644 --- a/lisp/emacs-lisp/disass.el +++ b/lisp/emacs-lisp/disass.el | |||
| @@ -129,7 +129,7 @@ redefine OBJECT if it is a symbol." | |||
| 129 | (setq args (help-function-arglist obj)) ;save arg list | 129 | (setq args (help-function-arglist obj)) ;save arg list |
| 130 | (setq obj (cdr obj)) ;throw lambda away | 130 | (setq obj (cdr obj)) ;throw lambda away |
| 131 | (setq obj (cdr obj))) | 131 | (setq obj (cdr obj))) |
| 132 | ((byte-code-function-p obj) | 132 | ((closurep obj) |
| 133 | (setq args (help-function-arglist obj))) | 133 | (setq args (help-function-arglist obj))) |
| 134 | (t (error "Compilation failed"))) | 134 | (t (error "Compilation failed"))) |
| 135 | (if (zerop indent) ; not a nested function | 135 | (if (zerop indent) ; not a nested function |
| @@ -178,7 +178,9 @@ redefine OBJECT if it is a symbol." | |||
| 178 | (t | 178 | (t |
| 179 | (insert "Uncompiled body: ") | 179 | (insert "Uncompiled body: ") |
| 180 | (let ((print-escape-newlines t)) | 180 | (let ((print-escape-newlines t)) |
| 181 | (prin1 (macroexp-progn obj) | 181 | (prin1 (macroexp-progn (if (interpreted-function-p obj) |
| 182 | (aref obj 1) | ||
| 183 | obj)) | ||
| 182 | (current-buffer)))))) | 184 | (current-buffer)))))) |
| 183 | (if interactive-p | 185 | (if interactive-p |
| 184 | (message ""))) | 186 | (message ""))) |
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index b27ffbca908..3414bb592c0 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el | |||
| @@ -4254,7 +4254,7 @@ code location is known." | |||
| 4254 | ((pred edebug--symbol-prefixed-p) nil) | 4254 | ((pred edebug--symbol-prefixed-p) nil) |
| 4255 | (_ | 4255 | (_ |
| 4256 | (when (and skip-next-lambda | 4256 | (when (and skip-next-lambda |
| 4257 | (not (memq (car-safe fun) '(closure lambda)))) | 4257 | (not (interpreted-function-p fun))) |
| 4258 | (warn "Edebug--strip-instrumentation expected an interpreted function:\n%S" fun)) | 4258 | (warn "Edebug--strip-instrumentation expected an interpreted function:\n%S" fun)) |
| 4259 | (unless skip-next-lambda | 4259 | (unless skip-next-lambda |
| 4260 | (edebug--unwrap-frame new-frame) | 4260 | (edebug--unwrap-frame new-frame) |
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 3475d944337..601cc7bf712 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el | |||
| @@ -1347,7 +1347,6 @@ Lisp function does not specify a special indentation." | |||
| 1347 | (put 'condition-case 'lisp-indent-function 2) | 1347 | (put 'condition-case 'lisp-indent-function 2) |
| 1348 | (put 'handler-case 'lisp-indent-function 1) ;CL | 1348 | (put 'handler-case 'lisp-indent-function 1) ;CL |
| 1349 | (put 'unwind-protect 'lisp-indent-function 1) | 1349 | (put 'unwind-protect 'lisp-indent-function 1) |
| 1350 | (put 'closure 'lisp-indent-function 2) | ||
| 1351 | 1350 | ||
| 1352 | (defun indent-sexp (&optional endpos) | 1351 | (defun indent-sexp (&optional endpos) |
| 1353 | "Indent each line of the list starting just after point. | 1352 | "Indent each line of the list starting just after point. |
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el index 5326c520601..36df143a82a 100644 --- a/lisp/emacs-lisp/nadvice.el +++ b/lisp/emacs-lisp/nadvice.el | |||
| @@ -185,7 +185,7 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.") | |||
| 185 | (defun advice--interactive-form-1 (function) | 185 | (defun advice--interactive-form-1 (function) |
| 186 | "Like `interactive-form' but preserves the static context if needed." | 186 | "Like `interactive-form' but preserves the static context if needed." |
| 187 | (let ((if (interactive-form function))) | 187 | (let ((if (interactive-form function))) |
| 188 | (if (or (null if) (not (eq 'closure (car-safe function)))) | 188 | (if (not (and if (interpreted-function-p function))) |
| 189 | if | 189 | if |
| 190 | (cl-assert (eq 'interactive (car if))) | 190 | (cl-assert (eq 'interactive (car if))) |
| 191 | (let ((form (cadr if))) | 191 | (let ((form (cadr if))) |
| @@ -193,14 +193,14 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.") | |||
| 193 | if | 193 | if |
| 194 | ;; The interactive is expected to be run in the static context | 194 | ;; The interactive is expected to be run in the static context |
| 195 | ;; that the function captured. | 195 | ;; that the function captured. |
| 196 | (let ((ctx (nth 1 function))) | 196 | (let ((ctx (aref function 2))) |
| 197 | `(interactive | 197 | `(interactive |
| 198 | ,(let* ((f (if (eq 'function (car-safe form)) (cadr form) form))) | 198 | ,(let* ((f (if (eq 'function (car-safe form)) (cadr form) form))) |
| 199 | ;; If the form jut returns a function, preserve the fact that | 199 | ;; If the form jut returns a function, preserve the fact that |
| 200 | ;; it just returns a function, which is an info we use in | 200 | ;; it just returns a function, which is an info we use in |
| 201 | ;; `advice--make-interactive-form'. | 201 | ;; `advice--make-interactive-form'. |
| 202 | (if (eq 'lambda (car-safe f)) | 202 | (if (eq 'lambda (car-safe f)) |
| 203 | `',(eval form ctx) | 203 | (eval form ctx) |
| 204 | `(eval ',form ',ctx)))))))))) | 204 | `(eval ',form ',ctx)))))))))) |
| 205 | 205 | ||
| 206 | (defun advice--interactive-form (function) | 206 | (defun advice--interactive-form (function) |
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el index 4da8e61aaa7..165d7c4b6e8 100644 --- a/lisp/emacs-lisp/oclosure.el +++ b/lisp/emacs-lisp/oclosure.el | |||
| @@ -146,7 +146,7 @@ | |||
| 146 | (setf (cl--find-class 'oclosure) | 146 | (setf (cl--find-class 'oclosure) |
| 147 | (oclosure--class-make 'oclosure | 147 | (oclosure--class-make 'oclosure |
| 148 | "The root parent of all OClosure types" | 148 | "The root parent of all OClosure types" |
| 149 | nil (list (cl--find-class 'function)) | 149 | nil (list (cl--find-class 'closure)) |
| 150 | '(oclosure))) | 150 | '(oclosure))) |
| 151 | (defun oclosure--p (oclosure) | 151 | (defun oclosure--p (oclosure) |
| 152 | (not (not (oclosure-type oclosure)))) | 152 | (not (not (oclosure-type oclosure)))) |
| @@ -431,75 +431,57 @@ ARGS and BODY are the same as for `lambda'." | |||
| 431 | 431 | ||
| 432 | (defun oclosure--fix-type (_ignore oclosure) | 432 | (defun oclosure--fix-type (_ignore oclosure) |
| 433 | "Helper function to implement `oclosure-lambda' via a macro. | 433 | "Helper function to implement `oclosure-lambda' via a macro. |
| 434 | This has 2 uses: | 434 | This is used as a marker which cconv uses to check that |
| 435 | - For interpreted code, this converts the representation of type information | 435 | immutable fields are indeed not mutated." |
| 436 | by moving it from the docstring to the environment. | 436 | (cl-assert (closurep oclosure)) |
| 437 | - For compiled code, this is used as a marker which cconv uses to check that | 437 | ;; This should happen only for interpreted closures since `cconv.el' |
| 438 | immutable fields are indeed not mutated." | 438 | ;; should have optimized away the call to this function. |
| 439 | (if (byte-code-function-p oclosure) | 439 | oclosure) |
| 440 | ;; Actually, this should never happen since `cconv.el' should have | ||
| 441 | ;; optimized away the call to this function. | ||
| 442 | oclosure | ||
| 443 | ;; For byte-coded functions, we store the type as a symbol in the docstring | ||
| 444 | ;; slot. For interpreted functions, there's no specific docstring slot | ||
| 445 | ;; so `Ffunction' turns the symbol into a string. | ||
| 446 | ;; We thus have convert it back into a symbol (via `intern') and then | ||
| 447 | ;; stuff it into the environment part of the closure with a special | ||
| 448 | ;; marker so we can distinguish this entry from actual variables. | ||
| 449 | (cl-assert (eq 'closure (car-safe oclosure))) | ||
| 450 | (let ((typename (nth 3 oclosure))) ;; The "docstring". | ||
| 451 | (cl-assert (stringp typename)) | ||
| 452 | (push (cons :type (intern typename)) | ||
| 453 | (cadr oclosure)) | ||
| 454 | oclosure))) | ||
| 455 | 440 | ||
| 456 | (defun oclosure--copy (oclosure mutlist &rest args) | 441 | (defun oclosure--copy (oclosure mutlist &rest args) |
| 442 | (cl-assert (closurep oclosure)) | ||
| 457 | (if (byte-code-function-p oclosure) | 443 | (if (byte-code-function-p oclosure) |
| 458 | (apply #'make-closure oclosure | 444 | (apply #'make-closure oclosure |
| 459 | (if (null mutlist) | 445 | (if (null mutlist) |
| 460 | args | 446 | args |
| 461 | (mapcar (lambda (arg) (if (pop mutlist) (list arg) arg)) args))) | 447 | (mapcar (lambda (arg) (if (pop mutlist) (list arg) arg)) args))) |
| 462 | (cl-assert (eq 'closure (car-safe oclosure)) | 448 | (cl-assert (consp (aref oclosure 1))) |
| 463 | nil "oclosure not closure: %S" oclosure) | 449 | (cl-assert (null (aref oclosure 3))) |
| 464 | (cl-assert (eq :type (caar (cadr oclosure)))) | 450 | (cl-assert (symbolp (aref oclosure 4))) |
| 465 | (let ((env (cadr oclosure))) | 451 | (let ((env (aref oclosure 2))) |
| 466 | `(closure | 452 | (make-interpreted-closure |
| 467 | (,(car env) | 453 | (aref oclosure 0) |
| 468 | ,@(named-let loop ((env (cdr env)) (args args)) | 454 | (aref oclosure 1) |
| 469 | (when args | 455 | (named-let loop ((env env) (args args)) |
| 470 | (cons (cons (caar env) (car args)) | 456 | (if (null args) env |
| 471 | (loop (cdr env) (cdr args))))) | 457 | (cons (cons (caar env) (car args)) |
| 472 | ,@(nthcdr (1+ (length args)) env)) | 458 | (loop (cdr env) (cdr args))))) |
| 473 | ,@(nthcdr 2 oclosure))))) | 459 | (aref oclosure 4) |
| 460 | (if (> (length oclosure) 5) | ||
| 461 | `(interactive ,(aref oclosure 5))))))) | ||
| 474 | 462 | ||
| 475 | (defun oclosure--get (oclosure index mutable) | 463 | (defun oclosure--get (oclosure index mutable) |
| 476 | (if (byte-code-function-p oclosure) | 464 | (cl-assert (closurep oclosure)) |
| 477 | (let* ((csts (aref oclosure 2)) | 465 | (let* ((csts (aref oclosure 2))) |
| 478 | (v (aref csts index))) | 466 | (if (vectorp csts) |
| 479 | (if mutable (car v) v)) | 467 | (let ((v (aref csts index))) |
| 480 | (cl-assert (eq 'closure (car-safe oclosure))) | 468 | (if mutable (car v) v)) |
| 481 | (cl-assert (eq :type (caar (cadr oclosure)))) | 469 | (cdr (nth index csts))))) |
| 482 | (cdr (nth (1+ index) (cadr oclosure))))) | ||
| 483 | 470 | ||
| 484 | (defun oclosure--set (v oclosure index) | 471 | (defun oclosure--set (v oclosure index) |
| 485 | (if (byte-code-function-p oclosure) | 472 | (cl-assert (closurep oclosure)) |
| 486 | (let* ((csts (aref oclosure 2)) | 473 | (let ((csts (aref oclosure 2))) |
| 487 | (cell (aref csts index))) | 474 | (if (vectorp csts) |
| 488 | (setcar cell v)) | 475 | (let ((cell (aref csts index))) |
| 489 | (cl-assert (eq 'closure (car-safe oclosure))) | 476 | (setcar cell v)) |
| 490 | (cl-assert (eq :type (caar (cadr oclosure)))) | 477 | (setcdr (nth index csts) v)))) |
| 491 | (setcdr (nth (1+ index) (cadr oclosure)) v))) | ||
| 492 | 478 | ||
| 493 | (defun oclosure-type (oclosure) | 479 | (defun oclosure-type (oclosure) |
| 494 | "Return the type of OCLOSURE, or nil if the arg is not a OClosure." | 480 | "Return the type of OCLOSURE, or nil if the arg is not an OClosure." |
| 495 | (if (byte-code-function-p oclosure) | 481 | (and (closurep oclosure) |
| 496 | (let ((type (and (> (length oclosure) 4) (aref oclosure 4)))) | 482 | (> (length oclosure) 4) |
| 497 | (if (symbolp type) type)) | 483 | (let ((type (aref oclosure 4))) |
| 498 | (and (eq 'closure (car-safe oclosure)) | 484 | (if (symbolp type) type)))) |
| 499 | (let* ((env (car-safe (cdr oclosure))) | ||
| 500 | (first-var (car-safe env))) | ||
| 501 | (and (eq :type (car-safe first-var)) | ||
| 502 | (cdr first-var)))))) | ||
| 503 | 485 | ||
| 504 | (defconst oclosure--accessor-prototype | 486 | (defconst oclosure--accessor-prototype |
| 505 | ;; Use `oclosure--lambda' to circumvent a bootstrapping problem: | 487 | ;; Use `oclosure--lambda' to circumvent a bootstrapping problem: |
diff --git a/lisp/help.el b/lisp/help.el index d4e39f04e53..10bd2ffec3f 100644 --- a/lisp/help.el +++ b/lisp/help.el | |||
| @@ -2349,9 +2349,8 @@ the same names as used in the original source code, when possible." | |||
| 2349 | ;; If definition is a macro, find the function inside it. | 2349 | ;; If definition is a macro, find the function inside it. |
| 2350 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) | 2350 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) |
| 2351 | (cond | 2351 | (cond |
| 2352 | ((and (byte-code-function-p def) (listp (aref def 0))) (aref def 0)) | 2352 | ((and (closurep def) (listp (aref def 0))) (aref def 0)) |
| 2353 | ((eq (car-safe def) 'lambda) (nth 1 def)) | 2353 | ((eq (car-safe def) 'lambda) (nth 1 def)) |
| 2354 | ((eq (car-safe def) 'closure) (nth 2 def)) | ||
| 2355 | ((and (featurep 'native-compile) | 2354 | ((and (featurep 'native-compile) |
| 2356 | (subrp def) | 2355 | (subrp def) |
| 2357 | (listp (subr-native-lambda-list def))) | 2356 | (listp (subr-native-lambda-list def))) |
diff --git a/lisp/profiler.el b/lisp/profiler.el index 4e02cd1d890..eb72f128c07 100644 --- a/lisp/profiler.el +++ b/lisp/profiler.el | |||
| @@ -275,10 +275,7 @@ Optional argument MODE means only check for the specified mode (cpu or mem)." | |||
| 275 | 275 | ||
| 276 | 276 | ||
| 277 | (define-hash-table-test 'profiler-function-equal #'function-equal | 277 | (define-hash-table-test 'profiler-function-equal #'function-equal |
| 278 | (lambda (f) (cond | 278 | (lambda (f) (if (closurep f) (aref f 1) f))) |
| 279 | ((byte-code-function-p f) (aref f 1)) | ||
| 280 | ((eq (car-safe f) 'closure) (cddr f)) | ||
| 281 | (t f)))) | ||
| 282 | 279 | ||
| 283 | (defun profiler-calltree-build-unified (tree log) | 280 | (defun profiler-calltree-build-unified (tree log) |
| 284 | ;; Let's try to unify all those partial backtraces into a single | 281 | ;; Let's try to unify all those partial backtraces into a single |
diff --git a/lisp/simple.el b/lisp/simple.el index e4629ce3db7..be64f3574e0 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -2703,15 +2703,14 @@ function as needed." | |||
| 2703 | (or (stringp doc) | 2703 | (or (stringp doc) |
| 2704 | (fixnump doc) (fixnump (cdr-safe doc)))))) | 2704 | (fixnump doc) (fixnump (cdr-safe doc)))))) |
| 2705 | (pcase function | 2705 | (pcase function |
| 2706 | ((pred byte-code-function-p) | 2706 | ((pred closurep) |
| 2707 | (when (> (length function) 4) | 2707 | (when (> (length function) 4) |
| 2708 | (let ((doc (aref function 4))) | 2708 | (let ((doc (aref function 4))) |
| 2709 | (when (funcall docstring-p doc) doc)))) | 2709 | (when (funcall docstring-p doc) doc)))) |
| 2710 | ((or (pred stringp) (pred vectorp)) "Keyboard macro.") | 2710 | ((or (pred stringp) (pred vectorp)) "Keyboard macro.") |
| 2711 | (`(keymap . ,_) | 2711 | (`(keymap . ,_) |
| 2712 | "Prefix command (definition is a keymap associating keystrokes with commands).") | 2712 | "Prefix command (definition is a keymap associating keystrokes with commands).") |
| 2713 | ((or `(lambda ,_args . ,body) `(closure ,_env ,_args . ,body) | 2713 | ((or `(lambda ,_args . ,body) `(autoload ,_file . ,body)) |
| 2714 | `(autoload ,_file . ,body)) | ||
| 2715 | (let ((doc (car body))) | 2714 | (let ((doc (car body))) |
| 2716 | (when (funcall docstring-p doc) | 2715 | (when (funcall docstring-p doc) |
| 2717 | doc))) | 2716 | doc))) |