aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorStefan Monnier2024-03-11 16:12:26 -0400
committerStefan Monnier2024-04-18 15:28:36 -0400
commit126be02077520a943252d0d219bb7677466d0168 (patch)
treef762237714f11b303c708f93f09a8dc72426bb2a /src/data.c
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 '')
-rw-r--r--src/data.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/src/data.c b/src/data.c
index 681054ff8cb..ea611ad1abf 100644
--- a/src/data.c
+++ b/src/data.c
@@ -248,7 +248,9 @@ a fixed set of types. */)
248 return XSUBR (object)->max_args == UNEVALLED ? Qspecial_form 248 return XSUBR (object)->max_args == UNEVALLED ? Qspecial_form
249 : SUBR_NATIVE_COMPILEDP (object) ? Qsubr_native_elisp 249 : SUBR_NATIVE_COMPILEDP (object) ? Qsubr_native_elisp
250 : Qprimitive_function; 250 : Qprimitive_function;
251 case PVEC_CLOSURE: return Qcompiled_function; 251 case PVEC_CLOSURE:
252 return CONSP (AREF (object, CLOSURE_CODE))
253 ? Qinterpreted_function : Qbyte_code_function;
252 case PVEC_BUFFER: return Qbuffer; 254 case PVEC_BUFFER: return Qbuffer;
253 case PVEC_CHAR_TABLE: return Qchar_table; 255 case PVEC_CHAR_TABLE: return Qchar_table;
254 case PVEC_BOOL_VECTOR: return Qbool_vector; 256 case PVEC_BOOL_VECTOR: return Qbool_vector;
@@ -518,12 +520,32 @@ DEFUN ("subrp", Fsubrp, Ssubrp, 1, 1, 0,
518 return Qnil; 520 return Qnil;
519} 521}
520 522
523DEFUN ("closurep", Fclosurep, Sclosurep,
524 1, 1, 0,
525 doc: /* Return t if OBJECT is a function of type `closure'. */)
526 (Lisp_Object object)
527{
528 if (CLOSUREP (object))
529 return Qt;
530 return Qnil;
531}
532
521DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p, 533DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
522 1, 1, 0, 534 1, 1, 0,
523 doc: /* Return t if OBJECT is a byte-compiled function object. */) 535 doc: /* Return t if OBJECT is a byte-compiled function object. */)
524 (Lisp_Object object) 536 (Lisp_Object object)
525{ 537{
526 if (CLOSUREP (object)) 538 if (CLOSUREP (object) && STRINGP (AREF (object, CLOSURE_CODE)))
539 return Qt;
540 return Qnil;
541}
542
543DEFUN ("interpreted-function-p", Finterpreted_function_p,
544 Sinterpreted_function_p, 1, 1, 0,
545 doc: /* Return t if OBJECT is a function of type `interpreted-function'. */)
546 (Lisp_Object object)
547{
548 if (CLOSUREP (object) && CONSP (AREF (object, CLOSURE_CODE)))
527 return Qt; 549 return Qt;
528 return Qnil; 550 return Qnil;
529} 551}
@@ -1174,17 +1196,11 @@ Value, if non-nil, is a list (interactive SPEC). */)
1174 else if (CONSP (fun)) 1196 else if (CONSP (fun))
1175 { 1197 {
1176 Lisp_Object funcar = XCAR (fun); 1198 Lisp_Object funcar = XCAR (fun);
1177 if (EQ (funcar, Qclosure) 1199 if (EQ (funcar, Qlambda))
1178 || EQ (funcar, Qlambda))
1179 { 1200 {
1180 Lisp_Object form = Fcdr (XCDR (fun)); 1201 Lisp_Object form = Fcdr (XCDR (fun));
1181 if (EQ (funcar, Qclosure))
1182 form = Fcdr (form);
1183 Lisp_Object spec = Fassq (Qinteractive, form); 1202 Lisp_Object spec = Fassq (Qinteractive, form);
1184 if (NILP (spec) && VALID_DOCSTRING_P (CAR_SAFE (form))) 1203 if (NILP (Fcdr (Fcdr (spec))))
1185 /* A "docstring" is a sign that we may have an OClosure. */
1186 genfun = true;
1187 else if (NILP (Fcdr (Fcdr (spec))))
1188 return spec; 1204 return spec;
1189 else 1205 else
1190 return list2 (Qinteractive, Fcar (Fcdr (spec))); 1206 return list2 (Qinteractive, Fcar (Fcdr (spec)));
@@ -1257,12 +1273,9 @@ The value, if non-nil, is a list of mode name symbols. */)
1257 else if (CONSP (fun)) 1273 else if (CONSP (fun))
1258 { 1274 {
1259 Lisp_Object funcar = XCAR (fun); 1275 Lisp_Object funcar = XCAR (fun);
1260 if (EQ (funcar, Qclosure) 1276 if (EQ (funcar, Qlambda))
1261 || EQ (funcar, Qlambda))
1262 { 1277 {
1263 Lisp_Object form = Fcdr (XCDR (fun)); 1278 Lisp_Object form = Fcdr (XCDR (fun));
1264 if (EQ (funcar, Qclosure))
1265 form = Fcdr (form);
1266 return Fcdr (Fcdr (Fassq (Qinteractive, form))); 1279 return Fcdr (Fcdr (Fassq (Qinteractive, form)));
1267 } 1280 }
1268 } 1281 }
@@ -4224,7 +4237,8 @@ syms_of_data (void)
4224 DEFSYM (Qspecial_form, "special-form"); 4237 DEFSYM (Qspecial_form, "special-form");
4225 DEFSYM (Qprimitive_function, "primitive-function"); 4238 DEFSYM (Qprimitive_function, "primitive-function");
4226 DEFSYM (Qsubr_native_elisp, "subr-native-elisp"); 4239 DEFSYM (Qsubr_native_elisp, "subr-native-elisp");
4227 DEFSYM (Qcompiled_function, "compiled-function"); 4240 DEFSYM (Qbyte_code_function, "byte-code-function");
4241 DEFSYM (Qinterpreted_function, "interpreted-function");
4228 DEFSYM (Qbuffer, "buffer"); 4242 DEFSYM (Qbuffer, "buffer");
4229 DEFSYM (Qframe, "frame"); 4243 DEFSYM (Qframe, "frame");
4230 DEFSYM (Qvector, "vector"); 4244 DEFSYM (Qvector, "vector");
@@ -4289,6 +4303,8 @@ syms_of_data (void)
4289 defsubr (&Smarkerp); 4303 defsubr (&Smarkerp);
4290 defsubr (&Ssubrp); 4304 defsubr (&Ssubrp);
4291 defsubr (&Sbyte_code_function_p); 4305 defsubr (&Sbyte_code_function_p);
4306 defsubr (&Sinterpreted_function_p);
4307 defsubr (&Sclosurep);
4292 defsubr (&Smodule_function_p); 4308 defsubr (&Smodule_function_p);
4293 defsubr (&Schar_or_string_p); 4309 defsubr (&Schar_or_string_p);
4294 defsubr (&Sthreadp); 4310 defsubr (&Sthreadp);