aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c111
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
91static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); 91static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
92static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); 92static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t);
93static Lisp_Object lambda_arity (Lisp_Object);
93 94
94static Lisp_Object 95static Lisp_Object
95specpdl_symbol (union specbinding *pdl) 96specpdl_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
2938DEFUN ("func-arity", Ffunc_arity, Sfunc_arity, 1, 1, 0,
2939 doc: /* Return minimum and maximum number of args allowed for FUNCTION.
2940FUNCTION must be a function of some kind.
2941The returned value is a cons cell (MIN . MAX). MIN is the minimum number
2942of args. MAX is the maximum number, or the symbol `many', for a
2943function 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. */
2989static Lisp_Object
2990lambda_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
2937DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode, 3047DEFUN ("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);