aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/emacs-lisp/cl-print.el
diff options
context:
space:
mode:
authorStefan Monnier2024-03-11 16:12:26 -0400
committerStefan Monnier2024-04-18 15:28:36 -0400
commit126be02077520a943252d0d219bb7677466d0168 (patch)
treef762237714f11b303c708f93f09a8dc72426bb2a /lisp/emacs-lisp/cl-print.el
parent7842af6095db4384898725fb4a14ebaa11379a34 (diff)
downloademacs-scratch/interpreted-function.tar.gz
emacs-scratch/interpreted-function.zip
Use a dedicated type to represent interpreted-function valuesscratch/interpreted-function
Change `function` so that when evaluating #'(lambda ...) we return an object of type `interpreted-function` rather than a list starting with one of `lambda` or `closure`. The new type reuses the existing PVEC_CLOSURE (nee PVEC_COMPILED) tag and tries to align the corresponding elements: - the arglist, the docstring, and the interactive-form go in the same slots as for byte-code functions. - the body of the function goes in the slot used for the bytecode string. - the lexical context goes in the slot used for the constants of bytecoded functions. The first point above means that `help-function-arglist`, `documentation`, and `interactive-form`s don't need to distinguish interpreted and bytecode functions any more. Main benefits of the change: - We can now reliably distinguish a list from a function value. - `cl-defmethod` can dispatch on `interactive-function` and `closure`. Dispatch on `function` also works now for interpreted functions but still won't work for functions represented as lists or as symbols, of course. - Function values are now self-evaluating. That was alrready the case when byte-compiled, but not when interpreted since (eval '(closure ...)) signals a void-function error. That also avoids false-positive warnings about "don't quote your lambdas" when doing things like `(mapcar ',func ...)`. * src/eval.c (Fmake_interpreted_closure): New function. (Ffunction): Use it and change calling convention of `Vinternal_make_interpreted_closure_function`. (FUNCTIONP, Fcommandp, eval_sub, funcall_general, funcall_lambda) (Ffunc_arity, lambda_arity): Simplify. (funcall_lambda): Adjust to new representation. (syms_of_eval): `defsubr` the new function. Remove definition of `Qclosure`. * lisp/emacs-lisp/cconv.el (cconv-make-interpreted-closure): Change calling convention and use `make-interpreted-closure`. * src/data.c (Fcl_type_of): Distinguish `byte-code-function`s from `interpreted-function`s. (Fclosurep, finterpreted_function_p): New functions. (Fbyte_code_function_p): Don't be confused by `interpreted-function`s. (Finteractive_form, Fcommand_modes): Simplify. (syms_of_data): Define new type symbols and `defsubr` the two new functions. * lisp/emacs-lisp/cl-print.el (cl-print-object) <interpreted-function>: New method. * lisp/emacs-lisp/oclosure.el (oclosure): Refine the parent to be `closure`. (oclosure--fix-type, oclosure-type): Simplify. (oclosure--copy, oclosure--get, oclosure--set): Adjust to new representation. * src/callint.c (Fcall_interactively): Adjust to new representation. * src/lread.c (bytecode_from_rev_list): * lisp/simple.el (function-documentation): * lisp/help.el (help-function-arglist): Remove the old `closure` case and adjust the byte-code case so it handles `interpreted-function`s. * lisp/emacs-lisp/cl-preloaded.el (closure): New type. (byte-code-function): Add it as a parent. (interpreted-function): Adjust parent (the type itself was already added earlier by accident). * lisp/emacs-lisp/bytecomp.el (byte-compile--reify-function): Adjust to new representation. (byte-compile): Use `interpreted-function-p`. * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Adjust to new representation. (side-effect-free-fns): Add `interpreted-function-p` and `closurep`. * src/profiler.c (trace_hash, ffunction_equal): Simplify. * lisp/profiler.el (profiler-function-equal): Simplify. * lisp/emacs-lisp/nadvice.el (advice--interactive-form-1): Use `interpreted-function-p`; adjust to new representation; and take advantage of the fact that function values are now self-evaluating. * lisp/emacs-lisp/lisp-mode.el (closure): Remove `lisp-indent-function` property. * lisp/emacs-lisp/disass.el (disassemble-internal): Adjust to new representation. * lisp/emacs-lisp/edebug.el (edebug--strip-instrumentation): Use `interpreted-function-p`. * lisp/emacs-lisp/comp-common.el (comp-known-type-specifiers): Add `closurep` and `interpreted-function-p`. * test/lisp/help-fns-tests.el (help-fns-test-lisp-defun): Adjust to more precise type info in `describe-function`. * test/lisp/erc/resources/erc-d/erc-d-tests.el (erc-d--render-entries): Use `interpreted-function-p`. * test/lisp/emacs-lisp/macroexp-resources/vk.el (vk-f4, vk-f5): Don't hardcode function values. * doc/lispref/functions.texi (Anonymous Functions): Don't suggest that function values are lists. Reword "self-quoting" to reflect the fact that #' doesn't return the exact same object. Update examples with the new shape of the return value. * doc/lispref/variables.texi (Lexical Binding): * doc/lispref/lists.texi (Rearrangement): * doc/lispref/control.texi (Handling Errors): Update examples to reflect new representation of function values.
Diffstat (limited to 'lisp/emacs-lisp/cl-print.el')
-rw-r--r--lisp/emacs-lisp/cl-print.el32
1 files changed, 32 insertions, 0 deletions
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)