diff options
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | lib.c | 63 | ||||
-rw-r--r-- | lib.h | 3 | ||||
-rw-r--r-- | txr.1 | 55 |
4 files changed, 124 insertions, 0 deletions
@@ -6856,6 +6856,9 @@ void eval_init(void) reg_fun(intern(lit("functionp"), user_package), func_n1(functionp)); reg_fun(intern(lit("interp-fun-p"), user_package), func_n1(interp_fun_p)); reg_fun(intern(lit("vm-fun-p"), user_package), func_n1(vm_fun_p)); + reg_fun(intern(lit("fun-fixparam-count"), user_package), func_n1(fun_fixparam_count)); + reg_fun(intern(lit("fun-optparam-count"), user_package), func_n1(fun_optparam_count)); + reg_fun(intern(lit("fun-variadic"), user_package), func_n1(fun_variadic)); reg_fun(intern(lit("ctx-form"), system_package), func_n1(ctx_form)); reg_fun(intern(lit("ctx-name"), system_package), func_n1(ctx_name)); @@ -6206,6 +6206,69 @@ val vm_fun_p(val obj) return (functionp(obj) && obj->f.functype == FVM) ? t : nil; } +static val get_param_counts(val params, cnum *fixparam, cnum *optparam) +{ + cnum fx = 0, oa = -1; + + for (; consp(params); params = us_cdr(params)) { + val param = us_car(params); + if (param == colon_k && oa < 0) { + oa = 0; + } else { + fx++; + oa += (oa >= 0); + } + } + + *fixparam = fx; + *optparam = oa; + return params; +} + +val fun_fixparam_count(val fun) +{ + type_check(lit("func-fixparam-count"), fun, FUN); + + if (fun->f.functype != FINTERP) { + return num(fun->f.fixparam); + } else { + val form = fun->f.f.interp_fun; + cnum fixparam, optparam; + val params = cadr(form); + (void) get_param_counts(params, &fixparam, &optparam); + return num(fixparam); + } +} + +val fun_optparam_count(val fun) +{ + type_check(lit("func-optparam-count"), fun, FUN); + + if (fun->f.functype != FINTERP) { + return num(fun->f.optargs); + } else { + val form = fun->f.f.interp_fun; + cnum fixparam, optparam; + val params = cadr(form); + (void) get_param_counts(params, &fixparam, &optparam); + return num(optparam); + } +} + +val fun_variadic(val fun) +{ + type_check(lit("func-variadic"), fun, FUN); + + if (fun->f.functype != FINTERP) { + return tnil(fun->f.variadic); + } else { + val form = fun->f.f.interp_fun; + cnum fixparam, optparam; + val params = cadr(form); + return tnil(get_param_counts(params, &fixparam, &optparam)); + } +} + static noreturn void callerror(val fun, val msg) { uses_or2; @@ -966,6 +966,9 @@ val us_func_set_env(val fun, val env); val functionp(val); val interp_fun_p(val); val vm_fun_p(val); +val fun_fixparam_count(val obj); +val fun_optparam_count(val obj); +val fun_variadic(val obj); val generic_funcall(val fun, struct args *); val funcall(val fun); val funcall1(val fun, val arg); @@ -17321,6 +17321,61 @@ function The environment object holds the captured bindings of a lexical closure. +.coNP Functions @ fun-fixparam-count and @ fun-optparam-count +.synb +.mets (fun-fixparam-count << func ) +.mets (fun-optparam-count << func ) +.syne +.desc +The +.code fun-fixparam-count +reports +.metn func 's +number of fixed parameters. The fixed parameters consist of the required +parameters and the optional parameters. Variadic functions have a parameter +which captures the remaining arguments which are in excess of the fixed +parameters. That parameter is not considered a fixed parameter and therefore +doesn't contribute to this count. + +The +.code fun-optparam-count +reports +.metn func 's +number of optional parameters. + +The +.meta func +argument must be a function. + +Note: if a function isn't variadic (see the +.meta fun-variadic +function) then the value reported by +.code fun-fixparam-count +represents the maximum number of arguments which can be passed to the function. +The minimum number of required arguments can be calculated for any function by +subtracting the value from +.code fun-optparam-count +from the value from +.codn fun-fixparam-count . + +.coNP Function @ fun-variadic +.synb +.mets (fun-variadic << func ) +.syne +.desc +The +.code fun-variadic +function returns +.code t +if +.meta func +is a variadic function, otherwise +.codn nil . + +The +.meta func +argument must be a function. + .coNP Function @ interp-fun-p .synb .mets (interp-fun-p << obj ) |