diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-05 01:22:58 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-05 01:22:58 -0800 |
commit | ecefd793e54d3cf0a56df705a18deb587d2a19c1 (patch) | |
tree | aac910f152b09dcd277001a6541e1cd50596b3bf | |
parent | a2665d2f02ce417851719f07c9e88bd642d59641 (diff) | |
download | txr-ecefd793e54d3cf0a56df705a18deb587d2a19c1.tar.gz txr-ecefd793e54d3cf0a56df705a18deb587d2a19c1.tar.bz2 txr-ecefd793e54d3cf0a56df705a18deb587d2a19c1.zip |
* eval.c (apply): Pass missing optional arguments as colon_k.
to functions for which this is requested.
(reg_fun_mark): New static function.
(eval_init): Register reduce_left and reduce_right as requiring
marking for missing optionals.
* lib.c (func_set_mark_missing): New function.
(generic_funcall): Pass missing optional arguments as colon_k
to functions for which this is requested.
(reduce_left, reduce_right): Handle missing values of init and key.
(func_f0, func_f1, func_f2, func_f3, func_f4, func_n0, func_n1,
func_n2, func_n3, func_n4, func_n5, func_n6, func_n7, func_f0v,
func_f1v, func_f2v, func_f3v, func_f4v, func_n0v, func_n1v,
func_n2v, func_n3v, func_n4v, func_n5v, func_n6v, func_n7v):
Initialize new mark_missing_args member of struct func.
* lib.h (struct func): New bitfield member, mark_missing_args.
(func_set_mark_missing): Declared.
(missingp, null_or_missing_p): New inline functions.
* txr.1: Updated descriptions of reduce-left and reduce-right.
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | eval.c | 19 | ||||
-rw-r--r-- | lib.c | 59 | ||||
-rw-r--r-- | lib.h | 7 | ||||
-rw-r--r-- | txr.1 | 22 |
5 files changed, 107 insertions, 24 deletions
@@ -1,3 +1,27 @@ +2014-02-05 Kaz Kylheku <kaz@kylheku.com> + + * eval.c (apply): Pass missing optional arguments as colon_k. + to functions for which this is requested. + (reg_fun_mark): New static function. + (eval_init): Register reduce_left and reduce_right as requiring + marking for missing optionals. + + * lib.c (func_set_mark_missing): New function. + (generic_funcall): Pass missing optional arguments as colon_k + to functions for which this is requested. + (reduce_left, reduce_right): Handle missing values of init and key. + (func_f0, func_f1, func_f2, func_f3, func_f4, func_n0, func_n1, + func_n2, func_n3, func_n4, func_n5, func_n6, func_n7, func_f0v, + func_f1v, func_f2v, func_f3v, func_f4v, func_n0v, func_n1v, + func_n2v, func_n3v, func_n4v, func_n5v, func_n6v, func_n7v): + Initialize new mark_missing_args member of struct func. + + * lib.h (struct func): New bitfield member, mark_missing_args. + (func_set_mark_missing): Declared. + (missingp, null_or_missing_p): New inline functions. + + * txr.1: Updated descriptions of reduce-left and reduce-right. + 2014-02-03 Kaz Kylheku <kaz@kylheku.com> * lib.c (nullp): Function removed. @@ -288,6 +288,7 @@ twocol: val apply(val fun, val arglist, val ctx_form) { val arg[32], *p = arg; + val missing; int variadic, fixparam, reqargs, nargs; if (symbolp(fun)) { @@ -299,6 +300,8 @@ val apply(val fun, val arglist, val ctx_form) type_check (fun, FUN); + missing = fun->f.mark_missing_args ? colon_k : nil; + if (!listp(arglist)) { val arglist_conv = tolist(arglist); type_assert (listp(arglist_conv), @@ -326,7 +329,7 @@ val apply(val fun, val arglist, val ctx_form) car(ctx_form), nao); for (; nargs < fixparam; nargs++) - *p++ = nil; + *p++ = missing; switch (fun->f.functype) { case F0: @@ -369,7 +372,7 @@ val apply(val fun, val arglist, val ctx_form) car(ctx_form), nao); for (; nargs < fixparam; nargs++) - *p++ = nil; + *p++ = missing; switch (fun->f.functype) { case FINTERP: @@ -2211,6 +2214,12 @@ static void reg_fun(val sym, val fun) sethash(top_fb, sym, cons(sym, fun)); } +static void reg_fun_mark(val sym, val fun) +{ + sethash(top_fb, sym, cons(sym, fun)); + func_set_mark_missing(fun); +} + static void c_var_mark(val obj) { struct c_var *cv = (struct c_var *) obj->co.handle; @@ -2389,8 +2398,10 @@ void eval_init(void) reg_fun(intern(lit("mappend"), user_package), func_n1v(mappendv)); reg_fun(intern(lit("mappend*"), user_package), func_n1v(lazy_mappendv)); reg_fun(apply_s, func_n1v(apply_intrinsic)); - reg_fun(intern(lit("reduce-left"), user_package), func_n4o(reduce_left, 2)); - reg_fun(intern(lit("reduce-right"), user_package), func_n4o(reduce_right, 2)); + reg_fun_mark(intern(lit("reduce-left"), user_package), + func_n4o(reduce_left, 2)); + reg_fun_mark(intern(lit("reduce-right"), user_package), + func_n4o(reduce_right, 2)); reg_fun(intern(lit("second"), user_package), func_n1(second)); reg_fun(intern(lit("third"), user_package), func_n1(third)); @@ -2833,6 +2833,7 @@ val func_f0(val env, val (*fun)(val)) obj->f.variadic = 0; obj->f.fixparam = 0; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2846,6 +2847,7 @@ val func_f1(val env, val (*fun)(val, val)) obj->f.variadic = 0; obj->f.fixparam = 1; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2859,6 +2861,7 @@ val func_f2(val env, val (*fun)(val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 2; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2872,6 +2875,7 @@ val func_f3(val env, val (*fun)(val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 3; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2885,6 +2889,7 @@ val func_f4(val env, val (*fun)(val, val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 4; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2898,6 +2903,7 @@ val func_n0(val (*fun)(void)) obj->f.variadic = 0; obj->f.fixparam = 0; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2911,6 +2917,7 @@ val func_n1(val (*fun)(val)) obj->f.variadic = 0; obj->f.fixparam = 1; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2924,6 +2931,7 @@ val func_n2(val (*fun)(val, val)) obj->f.variadic = 0; obj->f.fixparam = 2; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2937,6 +2945,7 @@ val func_n3(val (*fun)(val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 3; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2950,6 +2959,7 @@ val func_n4(val (*fun)(val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 4; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2963,6 +2973,7 @@ val func_n5(val (*fun)(val, val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 5; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2976,6 +2987,7 @@ val func_n6(val (*fun)(val, val, val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 6; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -2989,6 +3001,7 @@ val func_n7(val (*fun)(val, val, val, val, val, val, val)) obj->f.variadic = 0; obj->f.fixparam = 7; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3002,6 +3015,7 @@ val func_f0v(val env, val (*fun)(val, val)) obj->f.variadic = 1; obj->f.fixparam = 0; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3015,6 +3029,7 @@ val func_f1v(val env, val (*fun)(val env, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 1; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3028,6 +3043,7 @@ val func_f2v(val env, val (*fun)(val env, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 2; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3041,6 +3057,7 @@ val func_f3v(val env, val (*fun)(val env, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 3; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3054,6 +3071,7 @@ val func_f4v(val env, val (*fun)(val env, val, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 4; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3067,6 +3085,7 @@ val func_n0v(val (*fun)(val rest)) obj->f.variadic = 1; obj->f.fixparam = 0; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3080,6 +3099,7 @@ val func_n1v(val (*fun)(val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 1; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3093,6 +3113,7 @@ val func_n2v(val (*fun)(val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 2; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3106,6 +3127,7 @@ val func_n3v(val (*fun)(val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 3; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3119,6 +3141,7 @@ val func_n4v(val (*fun)(val, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 4; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3132,6 +3155,7 @@ val func_n5v(val (*fun)(val, val, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 5; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3145,6 +3169,7 @@ val func_n6v(val (*fun)(val, val, val, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 6; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3158,6 +3183,7 @@ val func_n7v(val (*fun)(val, val, val, val, val, val, val, val rest)) obj->f.variadic = 1; obj->f.fixparam = 7; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3206,6 +3232,7 @@ val func_interp(val env, val form) obj->f.variadic = 1; obj->f.fixparam = 0; obj->f.optargs = 0; + obj->f.mark_missing_args = 0; return obj; } @@ -3231,6 +3258,13 @@ val func_set_env(val fun, val env) return env; } +val func_set_mark_missing(val fun) +{ + type_check(fun, FUN); + fun->f.mark_missing_args = 1; + return nil; +} + val functionp(val obj) { return type(obj) == FUN ? t : nil; @@ -3244,9 +3278,11 @@ val interp_fun_p(val obj) static val generic_funcall(val fun, val arg[], int nargs) { int variadic, fixparam, reqargs; + val missing; type_check (fun, FUN); + missing = fun->f.mark_missing_args ? colon_k : nil; variadic = fun->f.variadic; fixparam = fun->f.fixparam; reqargs = fixparam - fun->f.optargs; @@ -3259,7 +3295,7 @@ static val generic_funcall(val fun, val arg[], int nargs) uw_throw(error_s, lit("funcall: too many arguments")); for (; nargs < fixparam; ) - arg[nargs++] = 0; + arg[nargs++] = missing; switch (fun->f.functype) { case F0: @@ -3301,7 +3337,7 @@ static val generic_funcall(val fun, val arg[], int nargs) uw_throw(error_s, lit("funcall: missing required arguments")); for (; nargs < fixparam; ) - arg[nargs++] = nil; + arg[nargs++] = missing; for (; nargs > fixparam; ) arglist = cons(arg[--nargs], arglist); @@ -3561,14 +3597,15 @@ val funcall4(val fun, val arg1, val arg2, val arg3, val arg4) val reduce_left(val fun, val list, val init, val key) { - if (!key) + if (null_or_missing_p(key)) key = identity_f; - if (!init && list) - init = pop(&list); - - if (!init && !list) - return funcall(fun); + if (missingp(init)) { + if (list) + init = pop(&list); + else + return funcall(fun); + } for (; list; list = cdr(list)) init = funcall2(fun, init, funcall1(key, car(list))); @@ -3578,11 +3615,11 @@ val reduce_left(val fun, val list, val init, val key) val reduce_right(val fun, val list, val init, val key) { - if (!key) + if (null_or_missing_p(key)) key = identity_f; if (list) { - if (!init) { + if (missingp(init)) { if (!rest(list)) return funcall1(key, first(list)); if (!rest(rest(list))) @@ -3594,7 +3631,7 @@ val reduce_right(val fun, val list, val init, val key) return funcall2(fun, funcall1(key, first(list)), init); /* fall through: init, and two or more items in list */ } - } else if (init) { + } else if (!missingp(init)) { return init; } else { return funcall(fun); @@ -106,7 +106,7 @@ struct func { unsigned fixparam : 7; /* total non-variadic parameters */ unsigned optargs : 7; /* fixparam - optargs = required args */ unsigned variadic : 1; - unsigned : 1; + unsigned mark_missing_args: 1; /* missing opt. args given as special value */ unsigned functype : 16; val env; union { @@ -601,6 +601,7 @@ val func_interp(val env, val form); val func_get_form(val fun); val func_get_env(val fun); val func_set_env(val fun, val env); +val func_set_mark_missing(val fun); val functionp(val); val interp_fun_p(val); val funcall(val fun); @@ -717,6 +718,10 @@ INLINE val nullp(val v) { return v ? nil : t; } #define nao ((obj_t *) (1 << TAG_SHIFT)) /* "not an object" sentinel value. */ +INLINE val missingp(val v) { return v == colon_k ? t : nil; } + +INLINE val null_or_missing_p(val v) { return (!v || v == colon_k) ? t : nil; } + #define if2(a, b) ((a) ? (b) : nil) #define if3(a, b, c) ((a) ? (b) : (c)) @@ -7247,18 +7247,17 @@ by <list> and <init-value> to a single value by the repeated application of <binary-function>. An effective list of operands is formed by combining <list> and -<init-value>. If <key-function> is specified and not nil, then -the items of <list> are mapped to a new values through <key-function>. -If an <init-value> is supplied and not nil, then in the -case of reduce-left, the effective list of operands is formed by prepending -<init-value> to <lits>. In the case of reduce-right, the effective +<init-value>. If <key-function> is specified, then the items of <list> are +mapped to a new values through <key-function>. If <init-value> is supplied, +then in the case of reduce-left, the effective list of operands is formed by +prepending <init-value> to <lits>. In the case of reduce-right, the effective operand list is produced by appending <init-value> to <list>. The production of the effective list can be expressed like this, -though this is not to be understood as the actual impelmentation: +though this is not to be understood as the actual implementation: ;; reduce-left - (let ((eff-list (append (if init-value (list init-value)) + (let ((eff-list (append (if init-value-present (list init-value)) [mapcar (or key-function identity) list]))) In the reduce-right case, the arguments to append are reversed. @@ -7273,6 +7272,13 @@ If the effective list contains one item, then that item is returned. Otherwise, the effective list contains two or more items, and is decimated as follows. +Note that an <init-value> specified as nil is not the same as a missing +<init-value>; this means that the initial value is the object nil. Omitting +<init-value> is the same as specifying a value of : (the colon symbol). +It is possible to specify <key-function> while omitting an <init-value> +argument. This is achieved by explicitly specifying : as the <init-value> +argument. + Under reduce-left, the leftmost pair of operands is removed from the list and passed as arguments to <binary-function>, in the same order that they appear in the list, and the resulting value initializes an @@ -7282,7 +7288,7 @@ from the list. After each call, the accumulator is updated with the return value of <binary-function>. The final value of the accumulator is returned. Under reduce-right, the list is processed right to left. The rightmost -pair of elements in the effetive list is removed, and passed as arguments to +pair of elements in the effective list is removed, and passed as arguments to <binary-function>, in the same order that they appear in the list. The resulting value initializes an accumulator. Then, for each remaining item in the list, <binary-function> is invoked on two arguments: the |