diff options
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c index 74b30e66bce..64a6655684c 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -90,6 +90,7 @@ union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; | |||
| 90 | 90 | ||
| 91 | static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); | 91 | static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); |
| 92 | static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); | 92 | static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); |
| 93 | static Lisp_Object lambda_arity (Lisp_Object); | ||
| 93 | 94 | ||
| 94 | static Lisp_Object | 95 | static Lisp_Object |
| 95 | specpdl_symbol (union specbinding *pdl) | 96 | specpdl_symbol (union specbinding *pdl) |
| @@ -2934,6 +2935,115 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | |||
| 2934 | return unbind_to (count, val); | 2935 | return unbind_to (count, val); |
| 2935 | } | 2936 | } |
| 2936 | 2937 | ||
| 2938 | DEFUN ("func-arity", Ffunc_arity, Sfunc_arity, 1, 1, 0, | ||
| 2939 | doc: /* Return minimum and maximum number of args allowed for FUNCTION. | ||
| 2940 | FUNCTION must be a function of some kind. | ||
| 2941 | The returned value is a cons cell (MIN . MAX). MIN is the minimum number | ||
| 2942 | of args. MAX is the maximum number, or the symbol `many', for a | ||
| 2943 | function with `&rest' args, or `unevalled' for a special form. */) | ||
| 2944 | (Lisp_Object function) | ||
| 2945 | { | ||
| 2946 | Lisp_Object original; | ||
| 2947 | Lisp_Object funcar; | ||
| 2948 | Lisp_Object result; | ||
| 2949 | short minargs, maxargs; | ||
| 2950 | |||
| 2951 | original = function; | ||
| 2952 | |||
| 2953 | retry: | ||
| 2954 | |||
| 2955 | /* Optimize for no indirection. */ | ||
| 2956 | function = original; | ||
| 2957 | if (SYMBOLP (function) && !NILP (function) | ||
| 2958 | && (function = XSYMBOL (function)->function, SYMBOLP (function))) | ||
| 2959 | function = indirect_function (function); | ||
| 2960 | |||
| 2961 | if (SUBRP (function)) | ||
| 2962 | result = Fsubr_arity (function); | ||
| 2963 | else if (COMPILEDP (function)) | ||
| 2964 | result = lambda_arity (function); | ||
| 2965 | else | ||
| 2966 | { | ||
| 2967 | if (NILP (function)) | ||
| 2968 | xsignal1 (Qvoid_function, original); | ||
| 2969 | if (!CONSP (function)) | ||
| 2970 | xsignal1 (Qinvalid_function, original); | ||
| 2971 | funcar = XCAR (function); | ||
| 2972 | if (!SYMBOLP (funcar)) | ||
| 2973 | xsignal1 (Qinvalid_function, original); | ||
| 2974 | if (EQ (funcar, Qlambda) | ||
| 2975 | || EQ (funcar, Qclosure)) | ||
| 2976 | result = lambda_arity (function); | ||
| 2977 | else if (EQ (funcar, Qautoload)) | ||
| 2978 | { | ||
| 2979 | Fautoload_do_load (function, original, Qnil); | ||
| 2980 | goto retry; | ||
| 2981 | } | ||
| 2982 | else | ||
| 2983 | xsignal1 (Qinvalid_function, original); | ||
| 2984 | } | ||
| 2985 | return result; | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | /* FUN must be either a lambda-expression or a compiled-code object. */ | ||
| 2989 | static Lisp_Object | ||
| 2990 | lambda_arity (Lisp_Object fun) | ||
| 2991 | { | ||
| 2992 | Lisp_Object val, syms_left, next; | ||
| 2993 | ptrdiff_t minargs, maxargs; | ||
| 2994 | bool optional; | ||
| 2995 | |||
| 2996 | if (CONSP (fun)) | ||
| 2997 | { | ||
| 2998 | if (EQ (XCAR (fun), Qclosure)) | ||
| 2999 | { | ||
| 3000 | fun = XCDR (fun); /* Drop `closure'. */ | ||
| 3001 | CHECK_LIST_CONS (fun, fun); | ||
| 3002 | } | ||
| 3003 | syms_left = XCDR (fun); | ||
| 3004 | if (CONSP (syms_left)) | ||
| 3005 | syms_left = XCAR (syms_left); | ||
| 3006 | else | ||
| 3007 | xsignal1 (Qinvalid_function, fun); | ||
| 3008 | } | ||
| 3009 | else if (COMPILEDP (fun)) | ||
| 3010 | { | ||
| 3011 | ptrdiff_t size = ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK; | ||
| 3012 | if (size <= COMPILED_STACK_DEPTH) | ||
| 3013 | xsignal1 (Qinvalid_function, fun); | ||
| 3014 | syms_left = AREF (fun, COMPILED_ARGLIST); | ||
| 3015 | if (INTEGERP (syms_left)) | ||
| 3016 | return get_byte_code_arity (syms_left); | ||
| 3017 | } | ||
| 3018 | else | ||
| 3019 | emacs_abort (); | ||
| 3020 | |||
| 3021 | minargs = maxargs = optional = 0; | ||
| 3022 | for (; CONSP (syms_left); syms_left = XCDR (syms_left)) | ||
| 3023 | { | ||
| 3024 | next = XCAR (syms_left); | ||
| 3025 | if (!SYMBOLP (next)) | ||
| 3026 | xsignal1 (Qinvalid_function, fun); | ||
| 3027 | |||
| 3028 | if (EQ (next, Qand_rest)) | ||
| 3029 | return Fcons (make_number (minargs), Qmany); | ||
| 3030 | else if (EQ (next, Qand_optional)) | ||
| 3031 | optional = 1; | ||
| 3032 | else | ||
| 3033 | { | ||
| 3034 | if (!optional) | ||
| 3035 | minargs++; | ||
| 3036 | maxargs++; | ||
| 3037 | } | ||
| 3038 | } | ||
| 3039 | |||
| 3040 | if (!NILP (syms_left)) | ||
| 3041 | xsignal1 (Qinvalid_function, fun); | ||
| 3042 | |||
| 3043 | return Fcons (make_number (minargs), make_number (maxargs)); | ||
| 3044 | } | ||
| 3045 | |||
| 3046 | |||
| 2937 | DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode, | 3047 | DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode, |
| 2938 | 1, 1, 0, | 3048 | 1, 1, 0, |
| 2939 | doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now. */) | 3049 | doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now. */) |
| @@ -3808,6 +3918,7 @@ alist of active lexical bindings. */); | |||
| 3808 | defsubr (&Seval); | 3918 | defsubr (&Seval); |
| 3809 | defsubr (&Sapply); | 3919 | defsubr (&Sapply); |
| 3810 | defsubr (&Sfuncall); | 3920 | defsubr (&Sfuncall); |
| 3921 | defsubr (&Sfunc_arity); | ||
| 3811 | defsubr (&Srun_hooks); | 3922 | defsubr (&Srun_hooks); |
| 3812 | defsubr (&Srun_hook_with_args); | 3923 | defsubr (&Srun_hook_with_args); |
| 3813 | defsubr (&Srun_hook_with_args_until_success); | 3924 | defsubr (&Srun_hook_with_args_until_success); |