aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/byte-opt.el3
-rw-r--r--lisp/emacs-lisp/bytecomp.el18
-rw-r--r--lisp/emacs-lisp/cconv.el38
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el15
-rw-r--r--lisp/emacs-lisp/cl-print.el32
-rw-r--r--lisp/emacs-lisp/comp-common.el2
-rw-r--r--lisp/emacs-lisp/disass.el6
-rw-r--r--lisp/emacs-lisp/edebug.el2
-rw-r--r--lisp/emacs-lisp/lisp-mode.el1
-rw-r--r--lisp/emacs-lisp/nadvice.el6
-rw-r--r--lisp/emacs-lisp/oclosure.el96
-rw-r--r--lisp/help.el3
-rw-r--r--lisp/profiler.el5
-rw-r--r--lisp/simple.el5
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.
2902FUN should be an interpreted closure." 2902FUN 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.
907This is intended to be called at runtime by the ELisp interpreter (when 907This is intended to be called at runtime by the ELisp interpreter (when
908the code has not been compiled). 908the code has not been compiled).
@@ -911,22 +911,27 @@ ENV is the runtime representation of the lexical environment,
911i.e. a list whose elements can be either plain symbols (which indicate 911i.e. a list whose elements can be either plain symbols (which indicate
912that this symbol should use dynamic scoping) or pairs (SYMBOL . VALUE) 912that this symbol should use dynamic scoping) or pairs (SYMBOL . VALUE)
913for the lexical bindings." 913for 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.
449You can access the object's internals with `aref'.
450The 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.
434This has 2 uses: 434This is used as a marker which cconv uses to check that
435- For interpreted code, this converts the representation of type information 435immutable 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)))