aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani2017-05-13 16:29:40 +0200
committerPhilipp Stephani2017-05-20 15:32:52 +0200
commit31fded0370c3aa6d2c4370cae21cdb7475873483 (patch)
treeacf2a7fda2d1b801b3aaf4cc9f168d3b6da77ec0 /src
parent6c7bf039e9c2e6daf548a95204740eeaf4c61abd (diff)
downloademacs-31fded0370c3aa6d2c4370cae21cdb7475873483.tar.gz
emacs-31fded0370c3aa6d2c4370cae21cdb7475873483.zip
Reimplement module functions
Instead of a lambda, create a new type containing all data required to call the function, and support it in the evaluator. Because this type now also needs to store the function documentation, it is too big for Lisp_Misc; use a pseudovector instead. That also has the nice benefit that we don't have to add special support to the garbage collector. Since the new type is user-visible, give it a predicate. Now we can easily support 'help-function-args' and 'func-arity'; add unit tests for these. * src/lisp.h (allocate_module_function, MODULE_FUNCTIONP) (XMODULE_FUNCTION): New pseudovector type 'module function'. * src/eval.c (FUNCTIONP): Also treat module functions as functions. (funcall_lambda, Ffuncall, eval_sub): Add support for calling module functions. (Ffunc_arity): Add support for detecting the arity of module functions. * src/emacs-module.c (module_make_function): Adapt to new structure. Return module function object directly instead of wrapping it in a lambda; remove FIXME. (funcall_module): New function to call module functions. Replaces `internal--module-call' and is called directly from eval.c. (syms_of_module): Remove internal helper function, which is no longer needed. (module_function_arity): New helper function. * src/data.c (Ftype_of): Adapt to new implementation. (Fmodule_function_p, syms_of_data): New user-visible function. Now that module functions are first-class objects, they deserve a predicate. Define it even if not compiled with --enable-modules so that Lisp code doesn't have to check for the function's existence. * src/doc.c (Fdocumentation): Support module functions. * src/print.c (print_object): Adapt to new implementation. * src/alloc.c (mark_object): Specialized garbage collector support is no longer needed. * lisp/help.el (help-function-arglist): Support module functions. While there, simplify the arity calculation by using `func-arity', which does the right thing for all kinds of functions. * test/data/emacs-module/mod-test.c: Amend docstring so we can test the argument list. * test/src/emacs-module-tests.el (mod-test-sum-docstring): Adapt to new docstring. (mod-test-non-local-exit-signal-test): Because `internal--module-call' is gone, the backtrace has changed and no longer leaks the implementation. (module--func-arity): New test for `func-arity'. (module--help-function-arglist): New test for `help-function-arglist'.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c8
-rw-r--r--src/data.c13
-rw-r--r--src/doc.c2
-rw-r--r--src/emacs-module.c50
-rw-r--r--src/eval.c17
-rw-r--r--src/lisp.h94
-rw-r--r--src/print.c12
7 files changed, 111 insertions, 85 deletions
diff --git a/src/alloc.c b/src/alloc.c
index faa14eebb36..b473ebd7ded 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3942,13 +3942,6 @@ make_user_ptr (void (*finalizer) (void *), void *p)
3942 uptr->p = p; 3942 uptr->p = p;
3943 return obj; 3943 return obj;
3944} 3944}
3945
3946/* Create a new module function environment object. */
3947Lisp_Object
3948make_module_function (void)
3949{
3950 return allocate_misc (Lisp_Misc_Module_Function);
3951}
3952#endif 3945#endif
3953 3946
3954static void 3947static void
@@ -6640,7 +6633,6 @@ mark_object (Lisp_Object arg)
6640 6633
6641#ifdef HAVE_MODULES 6634#ifdef HAVE_MODULES
6642 case Lisp_Misc_User_Ptr: 6635 case Lisp_Misc_User_Ptr:
6643 case Lisp_Misc_Module_Function:
6644 XMISCANY (obj)->gcmarkbit = true; 6636 XMISCANY (obj)->gcmarkbit = true;
6645 break; 6637 break;
6646#endif 6638#endif
diff --git a/src/data.c b/src/data.c
index 4242b90e628..25859105ee0 100644
--- a/src/data.c
+++ b/src/data.c
@@ -233,8 +233,6 @@ for example, (type-of 1) returns `integer'. */)
233 case Lisp_Misc_Finalizer: 233 case Lisp_Misc_Finalizer:
234 return Qfinalizer; 234 return Qfinalizer;
235#ifdef HAVE_MODULES 235#ifdef HAVE_MODULES
236 case Lisp_Misc_Module_Function:
237 return Qmodule_function;
238 case Lisp_Misc_User_Ptr: 236 case Lisp_Misc_User_Ptr:
239 return Quser_ptr; 237 return Quser_ptr;
240#endif 238#endif
@@ -278,6 +276,8 @@ for example, (type-of 1) returns `integer'. */)
278 else 276 else
279 return t; 277 return t;
280 } 278 }
279 case PVEC_MODULE_FUNCTION:
280 return Qmodule_function;
281 /* "Impossible" cases. */ 281 /* "Impossible" cases. */
282 case PVEC_XWIDGET: 282 case PVEC_XWIDGET:
283 case PVEC_OTHER: 283 case PVEC_OTHER:
@@ -494,6 +494,14 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
494 return Qnil; 494 return Qnil;
495} 495}
496 496
497DEFUN ("module-function-p", Fmodule_function_p, Smodule_function_p, 1, 1, NULL,
498 doc: /* Return t if OBJECT is a function loaded from a dynamic module. */
499 attributes: const)
500 (Lisp_Object object)
501{
502 return MODULE_FUNCTIONP (object) ? Qt : Qnil;
503}
504
497DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, 505DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
498 doc: /* Return t if OBJECT is a character or a string. */ 506 doc: /* Return t if OBJECT is a character or a string. */
499 attributes: const) 507 attributes: const)
@@ -3793,6 +3801,7 @@ syms_of_data (void)
3793 defsubr (&Smarkerp); 3801 defsubr (&Smarkerp);
3794 defsubr (&Ssubrp); 3802 defsubr (&Ssubrp);
3795 defsubr (&Sbyte_code_function_p); 3803 defsubr (&Sbyte_code_function_p);
3804 defsubr (&Smodule_function_p);
3796 defsubr (&Schar_or_string_p); 3805 defsubr (&Schar_or_string_p);
3797 defsubr (&Sthreadp); 3806 defsubr (&Sthreadp);
3798 defsubr (&Smutexp); 3807 defsubr (&Smutexp);
diff --git a/src/doc.c b/src/doc.c
index dd674e3bc05..345e18b9186 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -340,6 +340,8 @@ string is passed through `substitute-command-keys'. */)
340 fun = XCDR (fun); 340 fun = XCDR (fun);
341 if (SUBRP (fun)) 341 if (SUBRP (fun))
342 doc = make_number (XSUBR (fun)->doc); 342 doc = make_number (XSUBR (fun)->doc);
343 else if (MODULE_FUNCTIONP (fun))
344 doc = XMODULE_FUNCTION (fun)->documentation;
343 else if (COMPILEDP (fun)) 345 else if (COMPILEDP (fun))
344 { 346 {
345 if (PVSIZE (fun) <= COMPILED_DOC_STRING) 347 if (PVSIZE (fun) <= COMPILED_DOC_STRING)
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 0bc1b6c384b..99be4a748ee 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -362,30 +362,24 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
362 : min_arity <= max_arity))) 362 : min_arity <= max_arity)))
363 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity)); 363 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity));
364 364
365 Lisp_Object envobj = make_module_function (); 365 struct Lisp_Module_Function *envptr = allocate_module_function ();
366 struct Lisp_Module_Function *envptr = XMODULE_FUNCTION (envobj);
367 envptr->min_arity = min_arity; 366 envptr->min_arity = min_arity;
368 envptr->max_arity = max_arity; 367 envptr->max_arity = max_arity;
369 envptr->subr = subr; 368 envptr->subr = subr;
370 envptr->data = data; 369 envptr->data = data;
371 370
372 Lisp_Object doc = Qnil;
373 if (documentation) 371 if (documentation)
374 { 372 {
375 AUTO_STRING (unibyte_doc, documentation); 373 AUTO_STRING (unibyte_doc, documentation);
376 doc = code_convert_string_norecord (unibyte_doc, Qutf_8, false); 374 envptr->documentation =
375 code_convert_string_norecord (unibyte_doc, Qutf_8, false);
377 } 376 }
378 377
379 /* FIXME: Use a bytecompiled object, or even better a subr. */ 378 Lisp_Object envobj;
380 Lisp_Object ret = list4 (Qlambda, 379 XSET_MODULE_FUNCTION (envobj, envptr);
381 list2 (Qand_rest, Qargs), 380 eassert (MODULE_FUNCTIONP (envobj));
382 doc,
383 list4 (Qapply,
384 list2 (Qfunction, Qinternal__module_call),
385 envobj,
386 Qargs));
387 381
388 return lisp_to_value (ret); 382 return lisp_to_value (envobj);
389} 383}
390 384
391static emacs_value 385static emacs_value
@@ -648,17 +642,11 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
648 return Qt; 642 return Qt;
649} 643}
650 644
651DEFUN ("internal--module-call", Finternal_module_call, Sinternal_module_call, 1, MANY, 0, 645Lisp_Object
652 doc: /* Internal function to call a module function. 646funcall_module (const struct Lisp_Module_Function *const envptr,
653ENVOBJ is a save pointer to a module_fun_env structure. 647 ptrdiff_t nargs, Lisp_Object *arglist)
654ARGLIST is a list of arguments passed to SUBRPTR.
655usage: (module-call ENVOBJ &rest ARGLIST) */)
656 (ptrdiff_t nargs, Lisp_Object *arglist)
657{ 648{
658 Lisp_Object envobj = arglist[0]; 649 EMACS_INT len = nargs;
659 CHECK_TYPE (MODULE_FUNCTIONP (envobj), Qmodule_function_p, envobj);
660 struct Lisp_Module_Function *envptr = XMODULE_FUNCTION (envobj);
661 EMACS_INT len = nargs - 1;
662 eassume (0 <= envptr->min_arity); 650 eassume (0 <= envptr->min_arity);
663 if (! (envptr->min_arity <= len 651 if (! (envptr->min_arity <= len
664 && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity))) 652 && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity)))
@@ -672,12 +660,12 @@ usage: (module-call ENVOBJ &rest ARGLIST) */)
672 USE_SAFE_ALLOCA; 660 USE_SAFE_ALLOCA;
673 emacs_value *args; 661 emacs_value *args;
674 if (plain_values) 662 if (plain_values)
675 args = (emacs_value *) arglist + 1; 663 args = (emacs_value *) arglist;
676 else 664 else
677 { 665 {
678 args = SAFE_ALLOCA (len * sizeof *args); 666 args = SAFE_ALLOCA (len * sizeof *args);
679 for (ptrdiff_t i = 0; i < len; i++) 667 for (ptrdiff_t i = 0; i < len; i++)
680 args[i] = lisp_to_value (arglist[i + 1]); 668 args[i] = lisp_to_value (arglist[i]);
681 } 669 }
682 670
683 emacs_value ret = envptr->subr (&pub, len, args, envptr->data); 671 emacs_value ret = envptr->subr (&pub, len, args, envptr->data);
@@ -709,6 +697,15 @@ usage: (module-call ENVOBJ &rest ARGLIST) */)
709 } 697 }
710} 698}
711 699
700Lisp_Object
701module_function_arity (const struct Lisp_Module_Function *const function)
702{
703 const short minargs = function->min_arity;
704 const short maxargs = function->max_arity;
705 return Fcons (make_number (minargs),
706 maxargs == MANY ? Qmany : make_number (maxargs));
707}
708
712 709
713/* Helper functions. */ 710/* Helper functions. */
714 711
@@ -1025,7 +1022,4 @@ syms_of_module (void)
1025 DEFSYM (Qmodule_function_p, "module-function-p"); 1022 DEFSYM (Qmodule_function_p, "module-function-p");
1026 1023
1027 defsubr (&Smodule_load); 1024 defsubr (&Smodule_load);
1028
1029 DEFSYM (Qinternal__module_call, "internal--module-call");
1030 defsubr (&Sinternal_module_call);
1031} 1025}
diff --git a/src/eval.c b/src/eval.c
index 98d25cc4fed..f472efad52e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2261,7 +2261,7 @@ eval_sub (Lisp_Object form)
2261 } 2261 }
2262 } 2262 }
2263 } 2263 }
2264 else if (COMPILEDP (fun)) 2264 else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun))
2265 return apply_lambda (fun, original_args, count); 2265 return apply_lambda (fun, original_args, count);
2266 else 2266 else
2267 { 2267 {
@@ -2687,7 +2687,7 @@ FUNCTIONP (Lisp_Object object)
2687 2687
2688 if (SUBRP (object)) 2688 if (SUBRP (object))
2689 return XSUBR (object)->max_args != UNEVALLED; 2689 return XSUBR (object)->max_args != UNEVALLED;
2690 else if (COMPILEDP (object)) 2690 else if (COMPILEDP (object) || MODULE_FUNCTIONP (object))
2691 return true; 2691 return true;
2692 else if (CONSP (object)) 2692 else if (CONSP (object))
2693 { 2693 {
@@ -2742,7 +2742,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2742 2742
2743 if (SUBRP (fun)) 2743 if (SUBRP (fun))
2744 val = funcall_subr (XSUBR (fun), numargs, args + 1); 2744 val = funcall_subr (XSUBR (fun), numargs, args + 1);
2745 else if (COMPILEDP (fun)) 2745 else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun))
2746 val = funcall_lambda (fun, numargs, args + 1); 2746 val = funcall_lambda (fun, numargs, args + 1);
2747 else 2747 else
2748 { 2748 {
@@ -2892,7 +2892,8 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
2892 2892
2893/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR 2893/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR
2894 and return the result of evaluation. 2894 and return the result of evaluation.
2895 FUN must be either a lambda-expression or a compiled-code object. */ 2895 FUN must be either a lambda-expression, a compiled-code object,
2896 or a module function. */
2896 2897
2897static Lisp_Object 2898static Lisp_Object
2898funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, 2899funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
@@ -2949,6 +2950,10 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2949 } 2950 }
2950 lexenv = Qnil; 2951 lexenv = Qnil;
2951 } 2952 }
2953#ifdef HAVE_MODULES
2954 else if (MODULE_FUNCTIONP (fun))
2955 return funcall_module (XMODULE_FUNCTION (fun), nargs, arg_vector);
2956#endif
2952 else 2957 else
2953 emacs_abort (); 2958 emacs_abort ();
2954 2959
@@ -3060,6 +3065,10 @@ function with `&rest' args, or `unevalled' for a special form. */)
3060 result = Fsubr_arity (function); 3065 result = Fsubr_arity (function);
3061 else if (COMPILEDP (function)) 3066 else if (COMPILEDP (function))
3062 result = lambda_arity (function); 3067 result = lambda_arity (function);
3068#ifdef HAVE_MODULES
3069 else if (MODULE_FUNCTIONP (function))
3070 result = module_function_arity (XMODULE_FUNCTION (function));
3071#endif
3063 else 3072 else
3064 { 3073 {
3065 if (NILP (function)) 3074 if (NILP (function))
diff --git a/src/lisp.h b/src/lisp.h
index de3a548cb6c..ec8a8b1c098 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -464,7 +464,6 @@ enum Lisp_Misc_Type
464 Lisp_Misc_Save_Value, 464 Lisp_Misc_Save_Value,
465 Lisp_Misc_Finalizer, 465 Lisp_Misc_Finalizer,
466#ifdef HAVE_MODULES 466#ifdef HAVE_MODULES
467 Lisp_Misc_Module_Function,
468 Lisp_Misc_User_Ptr, 467 Lisp_Misc_User_Ptr,
469#endif 468#endif
470 /* Currently floats are not a misc type, 469 /* Currently floats are not a misc type,
@@ -885,6 +884,7 @@ enum pvec_type
885 PVEC_THREAD, 884 PVEC_THREAD,
886 PVEC_MUTEX, 885 PVEC_MUTEX,
887 PVEC_CONDVAR, 886 PVEC_CONDVAR,
887 PVEC_MODULE_FUNCTION,
888 888
889 /* These should be last, check internal_equal to see why. */ 889 /* These should be last, check internal_equal to see why. */
890 PVEC_COMPILED, 890 PVEC_COMPILED,
@@ -2386,28 +2386,6 @@ struct Lisp_User_Ptr
2386 void (*finalizer) (void *); 2386 void (*finalizer) (void *);
2387 void *p; 2387 void *p;
2388}; 2388};
2389
2390#include "emacs-module.h"
2391
2392/* Function prototype for the module Lisp functions. */
2393typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t,
2394 emacs_value [], void *);
2395
2396/* Function environments. */
2397
2398/* A function environment is an auxiliary structure used by
2399 `module_make_function' to store information about a module
2400 function. It is stored in a save pointer and retrieved by
2401 `internal--module-call'. Its members correspond to the arguments
2402 given to `module_make_function'. */
2403
2404struct Lisp_Module_Function
2405{
2406 struct Lisp_Misc_Any base;
2407 ptrdiff_t min_arity, max_arity;
2408 emacs_subr subr;
2409 void *data;
2410};
2411#endif 2389#endif
2412 2390
2413/* A finalizer sentinel. */ 2391/* A finalizer sentinel. */
@@ -2460,7 +2438,6 @@ union Lisp_Misc
2460 struct Lisp_Finalizer u_finalizer; 2438 struct Lisp_Finalizer u_finalizer;
2461#ifdef HAVE_MODULES 2439#ifdef HAVE_MODULES
2462 struct Lisp_User_Ptr u_user_ptr; 2440 struct Lisp_User_Ptr u_user_ptr;
2463 struct Lisp_Module_Function u_module_function;
2464#endif 2441#endif
2465 }; 2442 };
2466 2443
@@ -2509,19 +2486,6 @@ XUSER_PTR (Lisp_Object a)
2509 eassert (USER_PTRP (a)); 2486 eassert (USER_PTRP (a));
2510 return XUNTAG (a, Lisp_Misc); 2487 return XUNTAG (a, Lisp_Misc);
2511} 2488}
2512
2513INLINE bool
2514MODULE_FUNCTIONP (Lisp_Object o)
2515{
2516 return MISCP (o) && XMISCTYPE (o) == Lisp_Misc_Module_Function;
2517}
2518
2519INLINE struct Lisp_Module_Function *
2520XMODULE_FUNCTION (Lisp_Object o)
2521{
2522 eassert (MODULE_FUNCTIONP (o));
2523 return XUNTAG (o, Lisp_Misc);
2524}
2525#endif 2489#endif
2526 2490
2527 2491
@@ -3923,12 +3887,66 @@ extern void get_backtrace (Lisp_Object array);
3923Lisp_Object backtrace_top_function (void); 3887Lisp_Object backtrace_top_function (void);
3924extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); 3888extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
3925 3889
3890#include "emacs-module.h"
3891
3892/* Function prototype for the module Lisp functions. */
3893typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t,
3894 emacs_value [], void *);
3895
3896/* Function environments. */
3897
3898/* A function environment is an auxiliary structure used by
3899 `module_make_function' to store information about a module
3900 function. It is stored in a pseudovector. Its members correspond
3901 to the arguments given to `module_make_function'. */
3902
3903struct Lisp_Module_Function
3904{
3905 struct vectorlike_header header;
3906
3907 /* Fields traced by GC; these must come first. */
3908 Lisp_Object documentation;
3909
3910 /* Fields ignored by GC. */
3911 ptrdiff_t min_arity, max_arity;
3912 emacs_subr subr;
3913 void *data;
3914};
3915
3916INLINE struct Lisp_Module_Function *
3917allocate_module_function (void)
3918{
3919 return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function,
3920 /* Name of the first field to be
3921 ignored by GC. */
3922 min_arity,
3923 PVEC_MODULE_FUNCTION);
3924}
3925
3926INLINE bool
3927MODULE_FUNCTIONP (Lisp_Object o)
3928{
3929 return PSEUDOVECTORP (o, PVEC_MODULE_FUNCTION);
3930}
3931
3932INLINE struct Lisp_Module_Function *
3933XMODULE_FUNCTION (Lisp_Object o)
3934{
3935 eassert (MODULE_FUNCTIONP (o));
3936 return XUNTAG (o, Lisp_Vectorlike);
3937}
3938
3939#define XSET_MODULE_FUNCTION(var, ptr) \
3940 (XSETPSEUDOVECTOR (var, ptr, PVEC_MODULE_FUNCTION))
3941
3926#ifdef HAVE_MODULES 3942#ifdef HAVE_MODULES
3927/* Defined in alloc.c. */ 3943/* Defined in alloc.c. */
3928extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); 3944extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p);
3929extern Lisp_Object make_module_function (void);
3930 3945
3931/* Defined in emacs-module.c. */ 3946/* Defined in emacs-module.c. */
3947extern Lisp_Object funcall_module (const struct Lisp_Module_Function *,
3948 ptrdiff_t, Lisp_Object *);
3949extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *);
3932extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *); 3950extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *);
3933extern void syms_of_module (void); 3951extern void syms_of_module (void);
3934#endif 3952#endif
diff --git a/src/print.c b/src/print.c
index 7e411a80c88..be2e16a7499 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2051,6 +2051,13 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2051 } 2051 }
2052 break; 2052 break;
2053 2053
2054#ifdef HAVE_MODULES
2055 case PVEC_MODULE_FUNCTION:
2056 print_string (module_format_fun_env (XMODULE_FUNCTION (obj)),
2057 printcharfun);
2058 break;
2059#endif
2060
2054 case PVEC_OTHER: 2061 case PVEC_OTHER:
2055 case PVEC_FREE: 2062 case PVEC_FREE:
2056 emacs_abort (); 2063 emacs_abort ();
@@ -2103,11 +2110,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2103 printchar ('>', printcharfun); 2110 printchar ('>', printcharfun);
2104 break; 2111 break;
2105 } 2112 }
2106
2107 case Lisp_Misc_Module_Function:
2108 print_string (module_format_fun_env (XMODULE_FUNCTION (obj)),
2109 printcharfun);
2110 break;
2111#endif 2113#endif
2112 2114
2113 case Lisp_Misc_Finalizer: 2115 case Lisp_Misc_Finalizer: