diff options
| author | Philipp Stephani | 2017-05-13 16:29:40 +0200 |
|---|---|---|
| committer | Philipp Stephani | 2017-05-20 15:32:52 +0200 |
| commit | 31fded0370c3aa6d2c4370cae21cdb7475873483 (patch) | |
| tree | acf2a7fda2d1b801b3aaf4cc9f168d3b6da77ec0 /src | |
| parent | 6c7bf039e9c2e6daf548a95204740eeaf4c61abd (diff) | |
| download | emacs-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.c | 8 | ||||
| -rw-r--r-- | src/data.c | 13 | ||||
| -rw-r--r-- | src/doc.c | 2 | ||||
| -rw-r--r-- | src/emacs-module.c | 50 | ||||
| -rw-r--r-- | src/eval.c | 17 | ||||
| -rw-r--r-- | src/lisp.h | 94 | ||||
| -rw-r--r-- | src/print.c | 12 |
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. */ | ||
| 3947 | Lisp_Object | ||
| 3948 | make_module_function (void) | ||
| 3949 | { | ||
| 3950 | return allocate_misc (Lisp_Misc_Module_Function); | ||
| 3951 | } | ||
| 3952 | #endif | 3945 | #endif |
| 3953 | 3946 | ||
| 3954 | static void | 3947 | static 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 | ||
| 497 | DEFUN ("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 | |||
| 497 | DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, | 505 | DEFUN ("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); |
| @@ -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 | ||
| 391 | static emacs_value | 385 | static 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 | ||
| 651 | DEFUN ("internal--module-call", Finternal_module_call, Sinternal_module_call, 1, MANY, 0, | 645 | Lisp_Object |
| 652 | doc: /* Internal function to call a module function. | 646 | funcall_module (const struct Lisp_Module_Function *const envptr, |
| 653 | ENVOBJ is a save pointer to a module_fun_env structure. | 647 | ptrdiff_t nargs, Lisp_Object *arglist) |
| 654 | ARGLIST is a list of arguments passed to SUBRPTR. | ||
| 655 | usage: (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 | ||
| 700 | Lisp_Object | ||
| 701 | module_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 | ||
| 2897 | static Lisp_Object | 2898 | static Lisp_Object |
| 2898 | funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | 2899 | funcall_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. */ | ||
| 2393 | typedef 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 | |||
| 2404 | struct 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 | |||
| 2513 | INLINE bool | ||
| 2514 | MODULE_FUNCTIONP (Lisp_Object o) | ||
| 2515 | { | ||
| 2516 | return MISCP (o) && XMISCTYPE (o) == Lisp_Misc_Module_Function; | ||
| 2517 | } | ||
| 2518 | |||
| 2519 | INLINE struct Lisp_Module_Function * | ||
| 2520 | XMODULE_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); | |||
| 3923 | Lisp_Object backtrace_top_function (void); | 3887 | Lisp_Object backtrace_top_function (void); |
| 3924 | extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); | 3888 | extern 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. */ | ||
| 3893 | typedef 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 | |||
| 3903 | struct 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 | |||
| 3916 | INLINE struct Lisp_Module_Function * | ||
| 3917 | allocate_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 | |||
| 3926 | INLINE bool | ||
| 3927 | MODULE_FUNCTIONP (Lisp_Object o) | ||
| 3928 | { | ||
| 3929 | return PSEUDOVECTORP (o, PVEC_MODULE_FUNCTION); | ||
| 3930 | } | ||
| 3931 | |||
| 3932 | INLINE struct Lisp_Module_Function * | ||
| 3933 | XMODULE_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. */ |
| 3928 | extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); | 3944 | extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); |
| 3929 | extern Lisp_Object make_module_function (void); | ||
| 3930 | 3945 | ||
| 3931 | /* Defined in emacs-module.c. */ | 3946 | /* Defined in emacs-module.c. */ |
| 3947 | extern Lisp_Object funcall_module (const struct Lisp_Module_Function *, | ||
| 3948 | ptrdiff_t, Lisp_Object *); | ||
| 3949 | extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); | ||
| 3932 | extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *); | 3950 | extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *); |
| 3933 | extern void syms_of_module (void); | 3951 | extern 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: |