diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-02-21 18:13:52 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-02-21 18:13:52 -0800 |
commit | 72d59307630fd1bd9ee1c06cdad4cfb634bc9a3a (patch) | |
tree | 2232b5a5374c92d566f087f2bc5e5067a5fb8fd4 | |
parent | 216c446da541d2a2e68c57feee04bafce00013e5 (diff) | |
download | txr-72d59307630fd1bd9ee1c06cdad4cfb634bc9a3a.tar.gz txr-72d59307630fd1bd9ee1c06cdad4cfb634bc9a3a.tar.bz2 txr-72d59307630fd1bd9ee1c06cdad4cfb634bc9a3a.zip |
Introducing optional arguments.
* debug.c (help, show_bindings): put_string arguments reversed.
* eval.c (bind_args): Support colon notation in interpreted
function lambda lists for optional arguments. Improved error checking.
(apply): Allow optional arguments to be left out.
(dwim_loc): Reversed arguments to replace_str, replace_vec,
replace_list.
(eval_init): Numerous intrinsics now have arguments that are optional.
New function rand introduced which reverses arguments relative to
random. New intrinsic function hash introduced for alternative
construction of hashes.
* gc.c (sweep): Reversed arguments to put_char.
* hash.c (weak_keys_k, weak_vals_k, equal_based_k): New keyword
symbol variables.
(hashv): New function.
(hash_init): Intern new symbols.
* hash.h (weak_keys_k, weak_vals_k, equal_based_k, hashv): Declared.
* lib.c (colon_k): New keyword symbol variable.
(replace_list, replace_str, replace_vec): Arguments rearranged.
(tree_find): testfun becomes optional argument.
(int_str): base becomes optional argument.
(func_f0, func_f1, func_f2, func_f3, func_f4, func_n0,
func_n1, func_n2, func_n3, func_n4, func_f0v, func_f1v,
func_f2v, func_f3v, func_f4v, func_n0v, func_n1v,
func_n2v, func_n3v, func_n4v, func_interp): Initialize optargs to zero.
(func_n0o, func_n1o, func_n2o, func_n3o, func_n4o): New functions.
(cobj_print_op): Reversed arguments to put_string.
(find): testfun and keyfun become optional arguments.
(replace): Parameters rearranged and arguments rearranged in calls to
replace_list, replace_str and replace_vec.
(obj_init): colon_k initialized.
(obj_print, obj_pprint): Arguments reversed, and stream defaults
to std_output. Arguments reversed in calls to put_char and put_string.
(dump): Arguments reversed in call to put_char.
* lib.h (struct func): sizes of minparam, fixparam bitfields
adjusted. New bitfield optargs. New unnamed bitfield added so
the previous ones add up to 16 bits.
(colon_k): Declared.
(func_n0o, func_n1o, func_n2o, func_n3o, func_n4o): Declared.
(replace_list, replace_str, replace_vec, replace): Declarations updated.
* match.c (debuglf, dump_shell_string, dump_byte_string, dump_var,
do_output_line, extract): Reversed arguments to put_char and
-rw-r--r-- | ChangeLog | 77 | ||||
-rw-r--r-- | debug.c | 8 | ||||
-rw-r--r-- | eval.c | 145 | ||||
-rw-r--r-- | gc.c | 2 | ||||
-rw-r--r-- | hash.c | 13 | ||||
-rw-r--r-- | hash.h | 3 | ||||
-rw-r--r-- | lib.c | 255 | ||||
-rw-r--r-- | lib.h | 19 | ||||
-rw-r--r-- | match.c | 26 | ||||
-rw-r--r-- | parser.l | 9 | ||||
-rw-r--r-- | rand.c | 5 | ||||
-rw-r--r-- | rand.h | 1 | ||||
-rw-r--r-- | stream.c | 51 | ||||
-rw-r--r-- | stream.h | 6 | ||||
-rw-r--r-- | txr.1 | 24 | ||||
-rw-r--r-- | txr.c | 2 | ||||
-rw-r--r-- | txr.vim | 4 | ||||
-rw-r--r-- | unwind.c | 2 |
18 files changed, 449 insertions, 203 deletions
@@ -1,3 +1,80 @@ +2012-02-21 Kaz Kylheku <kaz@kylheku.com> + + Introducing optional arguments. + + * debug.c (help, show_bindings): put_string arguments reversed. + + * eval.c (bind_args): Support colon notation in interpreted + function lambda lists for optional arguments. Improved error checking. + (apply): Allow optional arguments to be left out. + (dwim_loc): Reversed arguments to replace_str, replace_vec, + replace_list. + (eval_init): Numerous intrinsics now have arguments that are optional. + New function rand introduced which reverses arguments relative to + random. New intrinsic function hash introduced for alternative + construction of hashes. + + * gc.c (sweep): Reversed arguments to put_char. + + * hash.c (weak_keys_k, weak_vals_k, equal_based_k): New keyword + symbol variables. + (hashv): New function. + (hash_init): Intern new symbols. + + * hash.h (weak_keys_k, weak_vals_k, equal_based_k, hashv): Declared. + + * lib.c (colon_k): New keyword symbol variable. + (replace_list, replace_str, replace_vec): Arguments rearranged. + (tree_find): testfun becomes optional argument. + (int_str): base becomes optional argument. + (func_f0, func_f1, func_f2, func_f3, func_f4, func_n0, + func_n1, func_n2, func_n3, func_n4, func_f0v, func_f1v, + func_f2v, func_f3v, func_f4v, func_n0v, func_n1v, + func_n2v, func_n3v, func_n4v, func_interp): Initialize optargs to zero. + (func_n0o, func_n1o, func_n2o, func_n3o, func_n4o): New functions. + (cobj_print_op): Reversed arguments to put_string. + (find): testfun and keyfun become optional arguments. + (replace): Parameters rearranged and arguments rearranged in calls to + replace_list, replace_str and replace_vec. + (obj_init): colon_k initialized. + (obj_print, obj_pprint): Arguments reversed, and stream defaults + to std_output. Arguments reversed in calls to put_char and put_string. + (dump): Arguments reversed in call to put_char. + + * lib.h (struct func): sizes of minparam, fixparam bitfields + adjusted. New bitfield optargs. New unnamed bitfield added so + the previous ones add up to 16 bits. + (colon_k): Declared. + (func_n0o, func_n1o, func_n2o, func_n3o, func_n4o): Declared. + (replace_list, replace_str, replace_vec, replace): Declarations updated. + + * match.c (debuglf, dump_shell_string, dump_byte_string, dump_var, + do_output_line, extract): Reversed arguments to put_char and + put_string. + + * parser.l (yyerrorf): Reversed arguments to put_char. + (grammar): Recognize : symbol in NESTED state. This is a keyword + symbol with the empty string as its name. + + * rand.c (rand): New function. + + * rand.h (rand): Declared. + + * stream.c (strlist_out_put_string): Reversed arguments to put_string. + (strlist_out_put_char): Reversed arguments to put_char. + (get_line, get_char, get_byte): Stream defaults to std_input. + (vformat_num, vformat_str, vformat): Reversed arguments to put_char. + (put_string, put_char, put_line): Arguments reversed; stream defaults + to std_output. + + * stream.h (put_string, put_line, put_char): Declarations updated. + + * txr.c (oom_realloc_handler): Arguments to put_line reversed. + + * unwind.c (uw_throw): Likewise. + + * txr.1, txr.vim: Updated. + 2012-02-19 Kaz Kylheku <kaz@kylheku.com> * txr.1: Corrected misleading text in description of output @@ -25,21 +25,21 @@ static int cols = 80; static void help(val stream) { - put_string(stream, - lit("commands:\n" + put_string(lit("commands:\n" "? - help s - step into form\n" "h - help n - step over form\n" "c - continue f - finish form\n" "v - show variable binding environment s - show current form\n" "b - set breakpoint by line number i - show current data\n" "d - delete breakpoint w - backtrace\n" - "l - list breakpoints\n")); + "l - list breakpoints\n"), + stream); } static void show_bindings(val env, val stream) { val level = zero; - put_string(stream, lit("bindings:\n")); + put_string(lit("bindings:\n"), stream); for (;; level = plus(level, one)) { if (nullp(env)) @@ -199,39 +199,64 @@ static val lookup_sym_lisp1(val env, val sym) static val bind_args(val env, val params, val args, val ctx_form) { val new_bindings = nil; + val optargs = nil; for (; args && consp(params); args = cdr(args), params = cdr(params)) { - val arg = car(args); val param = car(params); + if (param == colon_k) { + if (optargs) + goto twocol; + optargs = t; + params = cdr(params); + if (!consp(params)) + break; + param = car(params); + } + if (!bindable(param)) eval_error(ctx_form, lit("~a: ~s is not a bindable sybol"), car(ctx_form), param, nao); - new_bindings = acons(param, arg, new_bindings); + new_bindings = acons(param, car(args), new_bindings); } if (bindable(params)) { - val param = params; - if (!bindable(param)) { - eval_error(ctx_form, lit("~a: ~s is not a bindable sybol"), - car(ctx_form), param, nao); - } else { - new_bindings = acons(param, args, new_bindings); - } + new_bindings = acons(params, args, new_bindings); } else if (consp(params)) { - eval_error(ctx_form, lit("~s: too few arguments"), car(ctx_form), nao); + if (car(params) == colon_k) { + if (optargs) + goto twocol; + optargs = t; + params = cdr(params); + } + if (!optargs) + eval_error(ctx_form, lit("~s: too few arguments"), car(ctx_form), nao); + while (consp(params)) { + if (car(params) == colon_k) + goto twocol; + new_bindings = acons(car(params), nil, new_bindings); + params = cdr(params); + } + if (bindable(params)) + new_bindings = acons(params, args, new_bindings); + } else if (params) { + eval_error(ctx_form, lit("~a: ~s is not a bindable sybol"), + car(ctx_form), params, nao); } else if (args) { eval_error(ctx_form, lit("~s: too many arguments"), car(ctx_form), nao); } return make_env(new_bindings, nil, env); +twocol: + eval_error(ctx_form, lit("~a: multiple colons in parameter list"), + car(ctx_form), nao); } val apply(val fun, val arglist, val ctx_form) { val arg[32], *p = arg; - int variadic, minparam, nargs; + int variadic, fixparam, reqargs, nargs; if (symbolp(fun)) { val binding = gethash(top_fb, fun); @@ -246,7 +271,8 @@ val apply(val fun, val arglist, val ctx_form) (lit("apply arglist ~s is not a list"), arglist, nao)); variadic = fun->f.variadic; - minparam = fun->f.minparam; + fixparam = fun->f.fixparam; + reqargs = fixparam - fun->f.optargs; if (!variadic) { for (; arglist; arglist = cdr(arglist)) @@ -254,10 +280,17 @@ val apply(val fun, val arglist, val ctx_form) nargs = p - arg; - if (nargs != minparam) - eval_error(ctx_form, lit("~s: wrong number of arguments"), + if (nargs < reqargs) + eval_error(ctx_form, lit("~s: missing required arguments"), + car(ctx_form), nao); + + if (nargs > fixparam) + eval_error(ctx_form, lit("~s: too many arguments"), car(ctx_form), nao); + for (; nargs < fixparam; nargs++) + *p++ = nil; + switch (fun->f.functype) { case F0: return fun->f.f.f0(fun->f.env); @@ -283,13 +316,17 @@ val apply(val fun, val arglist, val ctx_form) internal_error("unsupported function type"); } } else { - for (; arglist && p - arg < minparam; arglist = cdr(arglist)) + for (; arglist && p - arg < fixparam; arglist = cdr(arglist)) *p++ = car(arglist); nargs = p - arg; - if (nargs < minparam) - eval_error(ctx_form, lit("apply: too few arguments"), nao); + if (nargs < reqargs) + eval_error(ctx_form, lit("~s: missing required arguments"), + car(ctx_form), nao); + + for (; nargs < fixparam; nargs++) + *p++ = nil; switch (fun->f.functype) { case FINTERP: @@ -714,7 +751,7 @@ static val *dwim_loc(val form, val env, val op, val newval, val *retval) eval_error(form, lit("[~s ~s]: ranges takes only set assignments"), obj, index, nao); - replace_str(obj, car(index), cdr(index), newval); + replace_str(obj, newval, car(index), cdr(index)); *retval = newval; return 0; } else { @@ -751,7 +788,7 @@ static val *dwim_loc(val form, val env, val op, val newval, val *retval) eval_error(form, lit("[~s ~s]: ranges take only set assignments"), obj, index, nao); - replace_vec(obj, car(index), cdr(index), newval); + replace_vec(obj, newval, car(index), cdr(index)); *retval = newval; return 0; } else { @@ -777,7 +814,7 @@ static val *dwim_loc(val form, val env, val op, val newval, val *retval) eval_error(form, lit("[~s ~s]: ranges take only simple assignments"), cell, index, nao); - newlist = replace_list(obj, car(index), cdr(index), newval); + newlist = replace_list(obj, newval, car(index), cdr(index)); tempform = list(op, second(form), cons(quote_s, cons(newlist, nil)), nao); op_modplace(tempform, env); @@ -1996,8 +2033,8 @@ void eval_init(void) reg_fun(intern(lit("rplacd"), user_package), func_n2(rplacd)); reg_fun(intern(lit("first"), user_package), func_n1(car)); reg_fun(rest_s, func_n1(cdr)); - reg_fun(intern(lit("sub-list"), user_package), func_n3(sub_list)); - reg_fun(intern(lit("replace-list"), user_package), func_n4(replace_list)); + reg_fun(intern(lit("sub-list"), user_package), func_n3o(sub_list, 1)); + reg_fun(intern(lit("replace-list"), user_package), func_n4o(replace_list, 2)); reg_fun(append_s, func_n0v(appendv)); reg_fun(intern(lit("append*"), user_package), func_n0v(lazy_appendv)); reg_fun(list_s, func_n0v(identity)); @@ -2017,8 +2054,8 @@ 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_n2(apply_intrinsic)); - reg_fun(intern(lit("reduce-left"), user_package), func_n4(reduce_left)); - reg_fun(intern(lit("reduce-right"), user_package), func_n4(reduce_right)); + 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(intern(lit("second"), user_package), func_n1(second)); reg_fun(intern(lit("third"), user_package), func_n1(third)); @@ -2034,10 +2071,10 @@ void eval_init(void) reg_fun(intern(lit("memq"), user_package), func_n2(memq)); reg_fun(intern(lit("memql"), user_package), func_n2(memql)); reg_fun(intern(lit("memqual"), user_package), func_n2(memqual)); - reg_fun(intern(lit("tree-find"), user_package), func_n3(tree_find)); - reg_fun(intern(lit("some"), user_package), func_n3(some_satisfy)); - reg_fun(intern(lit("all"), user_package), func_n3(all_satisfy)); - reg_fun(intern(lit("none"), user_package), func_n3(none_satisfy)); + reg_fun(intern(lit("tree-find"), user_package), func_n3o(tree_find, 2)); + reg_fun(intern(lit("some"), user_package), func_n3o(some_satisfy, 2)); + reg_fun(intern(lit("all"), user_package), func_n3o(all_satisfy, 2)); + reg_fun(intern(lit("none"), user_package), func_n3o(none_satisfy, 2)); reg_fun(intern(lit("eq"), user_package), eq_f); reg_fun(intern(lit("eql"), user_package), eql_f); reg_fun(intern(lit("equal"), user_package), equal_f); @@ -2066,10 +2103,11 @@ void eval_init(void) reg_fun(intern(lit("max"), user_package), func_n1v(maxv)); reg_fun(intern(lit("min"), user_package), func_n1v(minv)); - reg_fun(intern(lit("search-regex"), user_package), func_n4(search_regex)); - reg_fun(intern(lit("match-regex"), user_package), func_n3(match_regex)); + reg_fun(intern(lit("search-regex"), user_package), func_n4o(search_regex, 2)); + reg_fun(intern(lit("match-regex"), user_package), func_n3o(match_regex, 2)); reg_fun(intern(lit("make-hash"), user_package), func_n3(make_hash)); + reg_fun(intern(lit("hash"), user_package), func_n0v(hashv)); reg_fun(gethash_s, func_n3(gethash_n)); reg_fun(intern(lit("sethash"), user_package), func_n3(sethash)); reg_fun(intern(lit("pushhash"), user_package), func_n3(pushhash)); @@ -2084,14 +2122,14 @@ void eval_init(void) reg_fun(intern(lit("hash-eql"), user_package), func_n1(hash_eql)); reg_fun(intern(lit("hash-equal"), user_package), func_n1(hash_equal)); - reg_fun(intern(lit("eval"), user_package), func_n2(eval_intrinsic)); + reg_fun(intern(lit("eval"), user_package), func_n2o(eval_intrinsic, 1)); reg_var(intern(lit("*stdout*"), user_package), &std_output); reg_var(intern(lit("*stdin*"), user_package), &std_input); reg_var(intern(lit("*stderr*"), user_package), &std_error); reg_fun(intern(lit("format"), user_package), func_n2v(formatv)); - reg_fun(intern(lit("print"), user_package), func_n2(obj_print)); - reg_fun(intern(lit("pprint"), user_package), func_n2(obj_pprint)); + reg_fun(intern(lit("print"), user_package), func_n2o(obj_print, 1)); + reg_fun(intern(lit("pprint"), user_package), func_n2o(obj_pprint, 1)); reg_fun(intern(lit("tostring"), user_package), func_n1(tostring)); reg_fun(intern(lit("tostringp"), user_package), func_n1(tostringp)); reg_fun(intern(lit("make-string-input-stream"), user_package), func_n1(make_string_input_stream)); @@ -2100,13 +2138,13 @@ void eval_init(void) reg_fun(intern(lit("get-string-from-stream"), user_package), func_n1(get_string_from_stream)); reg_fun(intern(lit("make-strlist-output-stream"), user_package), func_n0(make_strlist_output_stream)); reg_fun(intern(lit("get-list-from-stream"), user_package), func_n1(get_list_from_stream)); - reg_fun(intern(lit("close-stream"), user_package), func_n2(close_stream)); - reg_fun(intern(lit("get-line"), user_package), func_n1(get_line)); - reg_fun(intern(lit("get-char"), user_package), func_n1(get_char)); - reg_fun(intern(lit("get-byte"), user_package), func_n1(get_byte)); - reg_fun(intern(lit("put-string"), user_package), func_n2(put_string)); - reg_fun(intern(lit("put-line"), user_package), func_n2(put_line)); - reg_fun(intern(lit("put-char"), user_package), func_n2(put_char)); + reg_fun(intern(lit("close-stream"), user_package), func_n2o(close_stream, 1)); + reg_fun(intern(lit("get-line"), user_package), func_n1o(get_line, 0)); + reg_fun(intern(lit("get-char"), user_package), func_n1o(get_char, 0)); + reg_fun(intern(lit("get-byte"), user_package), func_n1o(get_byte, 0)); + reg_fun(intern(lit("put-string"), user_package), func_n2o(put_string, 1)); + reg_fun(intern(lit("put-line"), user_package), func_n2o(put_line, 1)); + reg_fun(intern(lit("put-char"), user_package), func_n2o(put_char, 1)); reg_fun(intern(lit("flush-stream"), user_package), func_n1(flush_stream)); reg_fun(intern(lit("open-directory"), user_package), func_n1(open_directory)); reg_fun(intern(lit("open-file"), user_package), func_n2(open_file)); @@ -2119,7 +2157,7 @@ void eval_init(void) reg_fun(intern(lit("gensym"), user_package), func_n0v(gensymv)); reg_fun(intern(lit("make-package"), user_package), func_n1(make_package)); reg_fun(intern(lit("find-package"), user_package), func_n1(find_package)); - reg_fun(intern(lit("intern"), user_package), func_n2(intern)); + reg_fun(intern(lit("intern"), user_package), func_n2o(intern, 1)); reg_fun(intern(lit("symbolp"), user_package), func_n1(symbolp)); reg_fun(intern(lit("symbol-name"), user_package), func_n1(symbol_name)); reg_fun(intern(lit("symbol-package"), user_package), func_n1(symbol_package)); @@ -2133,17 +2171,17 @@ void eval_init(void) reg_fun(intern(lit("stringp"), user_package), func_n1(stringp)); reg_fun(intern(lit("lazy-stringp"), user_package), func_n1(lazy_stringp)); reg_fun(intern(lit("length-str"), user_package), func_n1(length_str)); - reg_fun(intern(lit("search-str"), user_package), func_n4(search_str)); - reg_fun(intern(lit("search-str-tree"), user_package), func_n4(search_str_tree)); - reg_fun(intern(lit("sub-str"), user_package), func_n3(sub_str)); - reg_fun(intern(lit("replace-str"), user_package), func_n4(replace_str)); - reg_fun(intern(lit("cat-str"), user_package), func_n2(cat_str)); + reg_fun(intern(lit("search-str"), user_package), func_n4o(search_str, 2)); + reg_fun(intern(lit("search-str-tree"), user_package), func_n4o(search_str_tree, 2)); + reg_fun(intern(lit("sub-str"), user_package), func_n3o(sub_str, 1)); + reg_fun(intern(lit("replace-str"), user_package), func_n4o(replace_str, 2)); + reg_fun(intern(lit("cat-str"), user_package), func_n2o(cat_str, 1)); reg_fun(intern(lit("split-str"), user_package), func_n2(split_str)); reg_fun(intern(lit("split-str-set"), user_package), func_n2(split_str_set)); reg_fun(intern(lit("list-str"), user_package), func_n1(list_str)); reg_fun(intern(lit("trim-str"), user_package), func_n1(trim_str)); reg_fun(intern(lit("string-lt"), user_package), func_n2(string_lt)); - reg_fun(intern(lit("int-str"), user_package), func_n2(int_str)); + reg_fun(intern(lit("int-str"), user_package), func_n2o(int_str, 1)); reg_fun(intern(lit("chrp"), user_package), func_n1(chrp)); reg_fun(intern(lit("chr-isalnum"), user_package), func_n1(chr_isalnum)); reg_fun(intern(lit("chr-isalpha"), user_package), func_n1(chr_isalpha)); @@ -2177,8 +2215,8 @@ void eval_init(void) reg_fun(intern(lit("vector-list"), user_package), func_n1(vector_list)); reg_fun(intern(lit("list-vector"), user_package), func_n1(list_vector)); reg_fun(intern(lit("copy-vec"), user_package), func_n1(copy_vec)); - reg_fun(intern(lit("sub-vec"), user_package), func_n3(sub_vec)); - reg_fun(intern(lit("replace-vec"), user_package), func_n4(replace_vec)); + reg_fun(intern(lit("sub-vec"), user_package), func_n3o(sub_vec, 1)); + reg_fun(intern(lit("replace-vec"), user_package), func_n4o(replace_vec, 2)); reg_fun(intern(lit("cat-vec"), user_package), func_n1(cat_vec)); reg_fun(intern(lit("assoc"), user_package), func_n2(assoc)); @@ -2190,10 +2228,10 @@ void eval_init(void) reg_fun(intern(lit("alist-nremove"), user_package), func_n1v(alist_nremove)); reg_fun(intern(lit("copy-cons"), user_package), func_n1(copy_cons)); reg_fun(intern(lit("copy-alist"), user_package), func_n1(copy_alist)); - reg_fun(intern(lit("merge"), user_package), func_n4(merge)); - reg_fun(intern(lit("sort"), user_package), func_n3(sort)); - reg_fun(intern(lit("find"), user_package), func_n4(find)); - reg_fun(intern(lit("set-diff"), user_package), func_n4(set_diff)); + reg_fun(intern(lit("merge"), user_package), func_n4o(merge, 2)); + reg_fun(intern(lit("sort"), user_package), func_n3o(sort, 2)); + reg_fun(intern(lit("find"), user_package), func_n4o(find, 2)); + reg_fun(intern(lit("set-diff"), user_package), func_n4o(set_diff, 2)); reg_fun(intern(lit("length"), user_package), func_n1(length)); @@ -2208,6 +2246,7 @@ void eval_init(void) reg_fun(intern(lit("random-state-p"), user_package), func_n1(random_state_p)); reg_fun(intern(lit("random-fixnum"), user_package), func_n1(random_fixnum)); reg_fun(intern(lit("random"), user_package), func_n2(random)); + reg_fun(intern(lit("rand"), user_package), func_n2o(rand, 1)); reg_fun(intern(lit("range"), user_package), func_n0v(rangev)); reg_fun(intern(lit("range*"), user_package), func_n0v(range_star_v)); @@ -429,7 +429,7 @@ static void sweep(void) if (0 && gc_dbg) { format(std_error, lit("~a: finalizing: "), progname, nao); obj_print(block, std_error); - put_char(std_error, chr('\n')); + put_char(chr('\n'), std_error); } finalize(block); block->t.type = (type_t) (block->t.type | FREE); @@ -63,6 +63,8 @@ struct hash_iter { val cons; }; +val weak_keys_k, weak_vals_k, equal_based_k; + /* * Dynamic list built up during gc. */ @@ -525,6 +527,17 @@ void hash_process_weak(void) reachable_weak_hashes = 0; } +val hashv(val args) +{ + val wkeys = memq(weak_keys_k, args); + val wvals = memq(weak_vals_k, args); + val equal = memq(equal_based_k, args); + return make_hash(wkeys, wvals, equal); +} + void hash_init(void) { + weak_keys_k = intern(lit("weak-keys"), keyword_package); + weak_vals_k = intern(lit("weak-vals"), keyword_package); + equal_based_k = intern(lit("equal-based"), keyword_package); } @@ -24,6 +24,8 @@ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +extern val weak_keys_k, weak_vals_k, equal_based_k; + val make_hash(val weak_keys, val weak_vals, val equal_based); val *gethash_l(val hash, val key, val *new_p); val gethash(val hash, val key); @@ -41,6 +43,7 @@ val hash_begin(val hash); val hash_next(val *iter); val hash_eql(val obj); val hash_equal(val obj); +val hashv(val args); void hash_process_weak(void); @@ -76,7 +76,7 @@ val error_s, type_error_s, internal_error_s; val numeric_error_s, range_error_s; val query_error_s, file_error_s, process_error_s; -val nothrow_k, args_k; +val nothrow_k, args_k, colon_k; val null_string; val nil_string; @@ -476,7 +476,7 @@ val sub_list(val list, val from, val to) } } -val replace_list(val list, val from, val to, val items) +val replace_list(val list, val items, val from, val to) { val len = nil; @@ -621,7 +621,9 @@ val memqual(val obj, val list) val tree_find(val obj, val tree, val testfun) { - if (funcall2(testfun, obj, tree)) + uses_or2; + + if (funcall2(or2(testfun, equal_f), obj, tree)) return t; else if (consp(tree)) return some_satisfy(tree, curry_123_2(func_n3(tree_find), @@ -1556,7 +1558,7 @@ val sub_str(val str_in, val from, val to) } } -val replace_str(val str_in, val from, val to, val items) +val replace_str(val str_in, val items, val from, val to) { val len = length_str(str_in); val len_it = length(items); @@ -1784,7 +1786,7 @@ val int_str(val str, val base) { const wchar_t *wcs = c_str(str); wchar_t *ptr; - cnum b = c_num(base); + cnum b = if3(base, c_num(base), 10); /* TODO: detect if we have wcstoll */ long value = wcstol(wcs, &ptr, b ? b : 10); @@ -2087,7 +2089,8 @@ val func_f0(val env, val (*fun)(val)) obj->f.env = env; obj->f.f.f0 = fun; obj->f.variadic = 0; - obj->f.minparam = 0; + obj->f.fixparam = 0; + obj->f.optargs = 0; return obj; } @@ -2099,7 +2102,8 @@ val func_f1(val env, val (*fun)(val, val)) obj->f.env = env; obj->f.f.f1 = fun; obj->f.variadic = 0; - obj->f.minparam = 1; + obj->f.fixparam = 1; + obj->f.optargs = 0; return obj; } @@ -2111,7 +2115,8 @@ val func_f2(val env, val (*fun)(val, val, val)) obj->f.env = env; obj->f.f.f2 = fun; obj->f.variadic = 0; - obj->f.minparam = 2; + obj->f.fixparam = 2; + obj->f.optargs = 0; return obj; } @@ -2123,7 +2128,8 @@ val func_f3(val env, val (*fun)(val, val, val, val)) obj->f.env = env; obj->f.f.f3 = fun; obj->f.variadic = 0; - obj->f.minparam = 3; + obj->f.fixparam = 3; + obj->f.optargs = 0; return obj; } @@ -2135,7 +2141,8 @@ val func_f4(val env, val (*fun)(val, val, val, val, val)) obj->f.env = env; obj->f.f.f4 = fun; obj->f.variadic = 0; - obj->f.minparam = 4; + obj->f.fixparam = 4; + obj->f.optargs = 0; return obj; } @@ -2147,7 +2154,8 @@ val func_n0(val (*fun)(void)) obj->f.env = nil; obj->f.f.n0 = fun; obj->f.variadic = 0; - obj->f.minparam = 0; + obj->f.fixparam = 0; + obj->f.optargs = 0; return obj; } @@ -2159,7 +2167,8 @@ val func_n1(val (*fun)(val)) obj->f.env = nil; obj->f.f.n1 = fun; obj->f.variadic = 0; - obj->f.minparam = 1; + obj->f.fixparam = 1; + obj->f.optargs = 0; return obj; } @@ -2171,7 +2180,8 @@ val func_n2(val (*fun)(val, val)) obj->f.env = nil; obj->f.f.n2 = fun; obj->f.variadic = 0; - obj->f.minparam = 2; + obj->f.fixparam = 2; + obj->f.optargs = 0; return obj; } @@ -2183,7 +2193,8 @@ val func_n3(val (*fun)(val, val, val)) obj->f.env = nil; obj->f.f.n3 = fun; obj->f.variadic = 0; - obj->f.minparam = 3; + obj->f.fixparam = 3; + obj->f.optargs = 0; return obj; } @@ -2195,7 +2206,8 @@ val func_n4(val (*fun)(val, val, val, val)) obj->f.env = nil; obj->f.f.n4 = fun; obj->f.variadic = 0; - obj->f.minparam = 4; + obj->f.fixparam = 4; + obj->f.optargs = 0; return obj; } @@ -2207,7 +2219,8 @@ val func_f0v(val env, val (*fun)(val, val)) obj->f.env = env; obj->f.f.f0v = fun; obj->f.variadic = 1; - obj->f.minparam = 0; + obj->f.fixparam = 0; + obj->f.optargs = 0; return obj; } @@ -2219,7 +2232,8 @@ val func_f1v(val env, val (*fun)(val env, val, val rest)) obj->f.env = env; obj->f.f.f1v = fun; obj->f.variadic = 1; - obj->f.minparam = 1; + obj->f.fixparam = 1; + obj->f.optargs = 0; return obj; } @@ -2231,7 +2245,8 @@ val func_f2v(val env, val (*fun)(val env, val, val, val rest)) obj->f.env = env; obj->f.f.f2v = fun; obj->f.variadic = 1; - obj->f.minparam = 2; + obj->f.fixparam = 2; + obj->f.optargs = 0; return obj; } @@ -2243,7 +2258,8 @@ val func_f3v(val env, val (*fun)(val env, val, val, val, val rest)) obj->f.env = env; obj->f.f.f3v = fun; obj->f.variadic = 1; - obj->f.minparam = 3; + obj->f.fixparam = 3; + obj->f.optargs = 0; return obj; } @@ -2255,7 +2271,8 @@ val func_f4v(val env, val (*fun)(val env, val, val, val, val, val rest)) obj->f.env = env; obj->f.f.f4v = fun; obj->f.variadic = 1; - obj->f.minparam = 4; + obj->f.fixparam = 4; + obj->f.optargs = 0; return obj; } @@ -2267,7 +2284,8 @@ val func_n0v(val (*fun)(val rest)) obj->f.env = nil; obj->f.f.n0v = fun; obj->f.variadic = 1; - obj->f.minparam = 0; + obj->f.fixparam = 0; + obj->f.optargs = 0; return obj; } @@ -2279,7 +2297,8 @@ val func_n1v(val (*fun)(val, val rest)) obj->f.env = nil; obj->f.f.n1v = fun; obj->f.variadic = 1; - obj->f.minparam = 1; + obj->f.fixparam = 1; + obj->f.optargs = 0; return obj; } @@ -2291,7 +2310,8 @@ val func_n2v(val (*fun)(val, val, val rest)) obj->f.env = nil; obj->f.f.n2v = fun; obj->f.variadic = 1; - obj->f.minparam = 2; + obj->f.fixparam = 2; + obj->f.optargs = 0; return obj; } @@ -2303,7 +2323,8 @@ val func_n3v(val (*fun)(val, val, val, val rest)) obj->f.env = nil; obj->f.f.n3v = fun; obj->f.variadic = 1; - obj->f.minparam = 3; + obj->f.fixparam = 3; + obj->f.optargs = 0; return obj; } @@ -2315,7 +2336,43 @@ val func_n4v(val (*fun)(val, val, val, val, val rest)) obj->f.env = nil; obj->f.f.n4v = fun; obj->f.variadic = 1; - obj->f.minparam = 4; + obj->f.fixparam = 4; + obj->f.optargs = 0; + return obj; +} + +val func_n0o(val (*fun)(void), int reqargs) +{ + val obj = func_n0(fun); + obj->f.optargs = 0 - reqargs; + return obj; +} + +val func_n1o(val (*fun)(val), int reqargs) +{ + val obj = func_n1(fun); + obj->f.optargs = 1 - reqargs; + return obj; +} + +val func_n2o(val (*fun)(val, val), int reqargs) +{ + val obj = func_n2(fun); + obj->f.optargs = 2 - reqargs; + return obj; +} + +val func_n3o(val (*fun)(val, val, val), int reqargs) +{ + val obj = func_n3(fun); + obj->f.optargs = 3 - reqargs; + return obj; +} + +val func_n4o(val (*fun)(val, val, val, val), int reqargs) +{ + val obj = func_n4(fun); + obj->f.optargs = 4 - reqargs; return obj; } @@ -2327,7 +2384,8 @@ val func_interp(val env, val form) obj->f.env = env; obj->f.f.interp_fun = form; obj->f.variadic = 1; - obj->f.minparam = 0; + obj->f.fixparam = 0; + obj->f.optargs = 0; return obj; } @@ -2911,7 +2969,7 @@ val sub_vec(val vec_in, val from, val to) } } -val replace_vec(val vec_in, val from, val to, val items) +val replace_vec(val vec_in, val items, val from, val to) { val len = length_vec(vec_in); val len_it = length(items); @@ -3244,7 +3302,7 @@ mem_t *cobj_handle(val cobj, val cls_sym) void cobj_print_op(val obj, val out) { - put_string(out, lit("#<")); + put_string(lit("#<"), out); obj_print(obj->co.cls, out); format(out, lit(": ~p>"), obj->co.handle, nao); } @@ -3518,11 +3576,13 @@ val sort(val list, val lessfun, val keyfun) val find(val list, val key, val testfun, val keyfun) { + uses_or2; + for (; list; list = cdr(list)) { val item = car(list); - val list_key = funcall1(keyfun, item); + val list_key = funcall1(or2(keyfun, identity_f), item); - if (funcall2(testfun, key, list_key)) + if (funcall2(or2(testfun, equal_f), key, list_key)) return item; } @@ -3610,7 +3670,7 @@ val ref(val seq, val ind) } } -val replace(val seq, val from, val to, val items) +val replace(val seq, val items, val from, val to) { if (seq == nil) goto list; @@ -3618,12 +3678,12 @@ val replace(val seq, val from, val to, val items) case CONS: case LCONS: list: - return replace_list(seq, from, to, items); + return replace_list(seq, items, from, to); case LIT: case STR: - return replace_str(seq, from, to, items); + return replace_str(seq, items, from, to); case VEC: - return replace_vec(seq, from, to, items); + return replace_vec(seq, items, from, to); default: type_mismatch(lit("replace: ~s is not a sequence"), cons, nao); } @@ -3783,6 +3843,7 @@ static void obj_init(void) args_k = intern(lit("args"), keyword_package); nothrow_k = intern(lit("nothrow"), keyword_package); + colon_k = intern(lit(""), keyword_package); equal_f = func_n2(equal); eq_f = func_n2(eq); @@ -3797,8 +3858,11 @@ static void obj_init(void) val obj_print(val obj, val out) { + if (out == nil) + out = std_output; + if (obj == nil) { - put_string(out, lit("nil")); + put_string(lit("nil"), out); return obj; } @@ -3809,35 +3873,35 @@ val obj_print(val obj, val out) val sym = car(obj); if (sym == quote_s || sym == qquote_s) { - put_char(out, chr('\'')); + put_char(chr('\''), out); obj_print(second(obj), out); } else if (sym == unquote_s) { - put_char(out, chr(',')); + put_char(chr(','), out); obj_print(second(obj), out); } else if (sym == splice_s) { - put_string(out, lit(",*")); + put_string(lit(",*"), out); obj_print(second(obj), out); } else { val iter; val closepar = chr(')'); if (sym == dwim_s && consp(cdr(obj))) { - put_char(out, chr('[')); + put_char(chr('['), out); obj = cdr(obj); closepar = chr(']'); } else { - put_char(out, chr('(')); + put_char(chr('('), out); } for (iter = obj; consp(iter); iter = cdr(iter)) { obj_print(car(iter), out); if (nullp(cdr(iter))) { - put_char(out, closepar); + put_char(closepar, out); } else if (consp(cdr(iter))) { - put_char(out, chr(' ')); + put_char(chr(' '), out); } else { - put_string(out, lit(" . ")); + put_string(lit(" . "), out); obj_print(cdr(iter), out); - put_char(out, closepar); + put_char(closepar, out); } } } @@ -3847,55 +3911,55 @@ val obj_print(val obj, val out) case STR: { const wchar_t *ptr; - put_char(out, chr('"')); + put_char(chr('"'), out); int semi_flag = 0; for (ptr = c_str(obj); *ptr; ptr++) { if (semi_flag && iswxdigit(*ptr)) - put_char(out, chr(';')); + put_char(chr(';'), out); semi_flag = 0; switch (*ptr) { - case '\a': put_string(out, lit("\\a")); break; - case '\b': put_string(out, lit("\\b")); break; - case '\t': put_string(out, lit("\\t")); break; - case '\n': put_string(out, lit("\\n")); break; - case '\v': put_string(out, lit("\\v")); break; - case '\f': put_string(out, lit("\\f")); break; - case '\r': put_string(out, lit("\\r")); break; - case '"': put_string(out, lit("\\\"")); break; - case '\\': put_string(out, lit("\\\\")); break; - case 27: put_string(out, lit("\\e")); break; + case '\a': put_string(lit("\\a"), out); break; + case '\b': put_string(lit("\\b"), out); break; + case '\t': put_string(lit("\\t"), out); break; + case '\n': put_string(lit("\\n"), out); break; + case '\v': put_string(lit("\\v"), out); break; + case '\f': put_string(lit("\\f"), out); break; + case '\r': put_string(lit("\\r"), out); break; + case '"': put_string(lit("\\\""), out); break; + case '\\': put_string(lit("\\\\"), out); break; + case 27: put_string(lit("\\e"), out); break; default: if (*ptr >= ' ') { - put_char(out, chr(*ptr)); + put_char(chr(*ptr), out); } else { format(out, lit("\\x~,02X"), num(*ptr), nao); semi_flag = 1; } } } - put_char(out, chr('"')); + put_char(chr('"'), out); } return obj; case CHR: { wchar_t ch = c_chr(obj); - put_string(out, lit("#\\")); + put_string(lit("#\\"), out); switch (ch) { - case '\0': put_string(out, lit("nul")); break; - case '\a': put_string(out, lit("alarm")); break; - case '\b': put_string(out, lit("backspace")); break; - case '\t': put_string(out, lit("tab")); break; - case '\n': put_string(out, lit("newline")); break; - case '\v': put_string(out, lit("vtab")); break; - case '\f': put_string(out, lit("page")); break; - case '\r': put_string(out, lit("return")); break; - case 27: put_string(out, lit("esc")); break; - case ' ': put_string(out, lit("space")); break; + case '\0': put_string(lit("nul"), out); break; + case '\a': put_string(lit("alarm"), out); break; + case '\b': put_string(lit("backspace"), out); break; + case '\t': put_string(lit("tab"), out); break; + case '\n': put_string(lit("newline"), out); break; + case '\v': put_string(lit("vtab"), out); break; + case '\f': put_string(lit("page"), out); break; + case '\r': put_string(lit("return"), out); break; + case 27: put_string(lit("esc"), out); break; + case ' ': put_string(lit("space"), out); break; default: if (ch >= ' ') - put_char(out, chr(ch)); + put_char(chr(ch), out); else format(out, lit("x~,02x"), num(ch), nao); } @@ -3908,12 +3972,12 @@ val obj_print(val obj, val out) case SYM: if (obj->s.package != user_package) { if (!obj->s.package) - put_char(out, chr('#')); + put_char(chr('#'), out); else if (obj->s.package != keyword_package) - put_string(out, obj->s.package->pk.name); - put_char(out, chr(':')); + put_string(obj->s.package->pk.name, out); + put_char(chr(':'), out); } - put_string(out, symbol_name(obj)); + put_string(symbol_name(obj), out); return obj; case PKG: format(out, lit("#<package: ~s>"), obj->pk.name, nao); @@ -3924,13 +3988,13 @@ val obj_print(val obj, val out) case VEC: { cnum i, length = c_num(obj->v.vec[vec_length]); - put_string(out, lit("#(")); + put_string(lit("#("), out); for (i = 0; i < length; i++) { obj_print(obj->v.vec[i], out); if (i < length - 1) - put_char(out, chr(' ')); + put_char(chr(' '), out); } - put_char(out, chr(')')); + put_char(chr(')'), out); } return obj; case LSTR: @@ -3950,8 +4014,11 @@ val obj_print(val obj, val out) val obj_pprint(val obj, val out) { + if (out == nil) + out = std_output; + if (obj == nil) { - put_string(out, lit("nil")); + put_string(lit("nil"), out); return obj; } @@ -3962,35 +4029,35 @@ val obj_pprint(val obj, val out) val sym = car(obj); if (sym == quote_s || sym == qquote_s) { - put_char(out, chr('\'')); + put_char(chr('\''), out); obj_pprint(second(obj), out); } else if (sym == unquote_s) { - put_char(out, chr(',')); + put_char(chr(','), out); obj_pprint(second(obj), out); } else if (sym == splice_s) { - put_string(out, lit(",*")); + put_string(lit(",*"), out); obj_pprint(second(obj), out); } else { val iter; val closepar = chr(')'); if (sym == dwim_s && consp(cdr(obj))) { - put_char(out, chr('[')); + put_char(chr('['), out); obj = cdr(obj); closepar = chr(']'); } else { - put_char(out, chr('(')); + put_char(chr('('), out); } for (iter = obj; consp(iter); iter = cdr(iter)) { obj_pprint(car(iter), out); if (nullp(cdr(iter))) { - put_char(out, closepar); + put_char(closepar, out); } else if (consp(cdr(iter))) { - put_char(out, chr(' ')); + put_char(chr(' '), out); } else { - put_string(out, lit(" . ")); + put_string(lit(" . "), out); obj_pprint(cdr(iter), out); - put_char(out, closepar); + put_char(closepar, out); } } } @@ -3998,17 +4065,17 @@ val obj_pprint(val obj, val out) return obj; case LIT: case STR: - put_string(out, obj); + put_string(obj, out); return obj; case CHR: - put_char(out, obj); + put_char(obj, out); return obj; case NUM: case BGNUM: format(out, lit("~s"), obj, nao); return obj; case SYM: - put_string(out, symbol_name(obj)); + put_string(symbol_name(obj), out); return obj; case PKG: format(out, lit("#<package: ~s>"), obj->pk.name, nao); @@ -4019,13 +4086,13 @@ val obj_pprint(val obj, val out) case VEC: { cnum i, length = c_num(obj->v.vec[vec_length]); - put_string(out, lit("#(")); + put_string(lit("#("), out); for (i = 0; i < length; i++) { obj_pprint(obj->v.vec[i], out); if (i < length - 1) - put_char(out, chr(' ')); + put_char(chr(' '), out); } - put_char(out, chr(')')); + put_char(chr(')'), out); } return obj; case LSTR: @@ -4080,7 +4147,7 @@ void init(const wchar_t *pn, mem_t *(*oom)(mem_t *, size_t), void dump(val obj, val out) { obj_print(obj, out); - put_char(out, chr('\n')); + put_char(chr('\n'), out); } /* @@ -89,8 +89,10 @@ struct package { struct func { type_t type; - unsigned minparam : 15; + unsigned fixparam : 7; /* total non-variadic parameters */ + unsigned optargs : 7; /* fixparam - optargs = required args */ unsigned variadic : 1; + unsigned : 1; functype_t functype : 16; val env; union { @@ -291,7 +293,7 @@ extern val error_s, type_error_s, internal_error_s; extern val numeric_error_s, range_error_s; extern val query_error_s, file_error_s, process_error_s; -extern val nothrow_k, args_k; +extern val nothrow_k, args_k, colon_k; extern val null_string; extern val null_list; /* (nil) */ @@ -337,7 +339,7 @@ val append2(val list1, val list2); val nappend2(val list1, val list2); val appendv(val lists); val sub_list(val list, val from, val to); -val replace_list(val list, val from, val to, val items); +val replace_list(val list, val items, val from, val to); val lazy_appendv(val lists); val ldiff(val list1, val list2); val flatten(val list); @@ -420,7 +422,7 @@ val length_str(val str); const wchar_t *c_str(val str); val search_str(val haystack, val needle, val start_num, val from_end); val search_str_tree(val haystack, val tree, val start_num, val from_end); -val replace_str(val str_in, val from, val to, val items); +val replace_str(val str_in, val items, val from, val to); val sub_str(val str_in, val from_num, val to_num); val cat_str(val list, val sep); val split_str(val str, val sep); @@ -482,6 +484,11 @@ val func_n1v(val (*fun)(val, val rest)); val func_n2v(val (*fun)(val, val, val rest)); val func_n3v(val (*fun)(val, val, val, val rest)); val func_n4v(val (*fun)(val, val, val, val, val rest)); +val func_n0o(val (*fun)(void), int reqargs); +val func_n1o(val (*fun)(val), int reqargs); +val func_n2o(val (*fun)(val, val), int reqargs); +val func_n3o(val (*fun)(val, val, val), int reqargs); +val func_n4o(val (*fun)(val, val, val, val), int reqargs); val func_interp(val env, val form); val func_get_form(val fun); val func_get_env(val fun); @@ -520,7 +527,7 @@ val vector_list(val list); val list_vector(val vector); val copy_vec(val vec); val sub_vec(val vec_in, val from, val to); -val replace_vec(val vec_in, val from, val to, val items); +val replace_vec(val vec_in, val items, val from, val to); val cat_vec(val list); val lazy_stream_cons(val stream); val lazy_str(val list, val term, val limit); @@ -559,7 +566,7 @@ val set_diff(val list1, val list2, val testfun, val keyfun); val length(val seq); val sub(val seq, val from, val to); val ref(val seq, val ind); -val replace(val seq, val from, val to, val items); +val replace(val seq, val items, val from, val to); val env(void); val obj_print(val obj, val stream); val obj_pprint(val obj, val stream); @@ -73,7 +73,7 @@ static void debuglf(val form, val fmt, ...) format(std_error, lit("~a: (~a:~a) "), prog_string, spec_file_str, source_loc(form), nao); vformat(std_error, fmt, vl); - put_char(std_error, chr('\n')); + put_char(chr('\n'), std_error); va_end (vl); } } @@ -113,23 +113,23 @@ static void dump_shell_string(const wchar_t *str) { int ch; - put_char(std_output, chr('"')); + put_char(chr('"'), std_output); while ((ch = *str++) != 0) { switch (ch) { case '"': case '`': case '$': case '\\': case '\n': - put_char(std_output, chr('\\')); + put_char(chr('\\'), std_output); /* fallthrough */ default: - put_char(std_output, chr(ch)); + put_char(chr(ch), std_output); } } - put_char(std_output, chr('"')); + put_char(chr('"'), std_output); } static void dump_byte_string(const char *str) { while (*str) - put_char(std_output, chr(*str++)); + put_char(chr(*str++), std_output); } @@ -162,12 +162,12 @@ static void dump_var(val var, char *pfx1, size_t len1, obj_pprint(value, ss); str = get_string_from_stream(ss); - put_string(std_output, var); + put_string(var, std_output); dump_byte_string(pfx1); dump_byte_string(pfx2); - put_char(std_output, chr('=')); + put_char(chr('='), std_output); dump_shell_string(c_str(str)); - put_char(std_output, chr('\n')); + put_char(chr('\n'), std_output); } } @@ -1576,7 +1576,7 @@ static void do_output_line(val bindings, val specline, val filter, val out) if (str == nil) sem_error(specline, lit("bad substitution: ~a"), second(elem), nao); - put_string(out, str); + put_string(str, out); } else if (directive == rep_s) { val clauses = cdr(elem); val args = pop(&clauses); @@ -1679,7 +1679,7 @@ static void do_output_line(val bindings, val specline, val filter, val out) } break; case STR: - put_string(out, elem); + put_string(elem, out); break; case 0: break; @@ -1798,7 +1798,7 @@ static void do_output(val bindings, val specs, val filter, val out) } do_output_line(bindings, specline, filter, out); - put_char(out, chr('\n')); + put_char(chr('\n'), out); } } @@ -3565,7 +3565,7 @@ int extract(val spec, val files, val predefined_bindings) } if (!success) - put_line(std_output, lit("false")); + put_line(lit("false"), std_output); } return success ? 0 : EXIT_FAILURE; @@ -88,7 +88,7 @@ void yyerrorf(val fmt, ...) format(std_error, lit("~a: (~a:~a): "), prog_string, spec_file_str, num(lineno), nao); vformat(std_error, fmt, vl); - put_char(std_error, chr('\n')); + put_char(chr('\n'), std_error); va_end (vl); } errors++; @@ -211,6 +211,13 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} return IDENT; } } +<NESTED>: { + if (yy_top_state() == INITIAL + || yy_top_state() == QSILIT) + yy_pop_state(); + yylval.lexeme = utf8_dup_from(""); + return KEYWORD; + } <SPECIAL>\({WS}all{WS}\) { yy_pop_state(); @@ -241,6 +241,11 @@ invalid: modulus, nao); } +val rand(val modulus, val state) +{ + return random(state, modulus); +} + void rand_init(void) { prot1(&random_state); @@ -30,4 +30,5 @@ val make_random_state(val seed); val random_state_p(val obj); val random_fixnum(val state); val random(val state, val modulus); +val rand(val modulus, val state); void rand_init(void); @@ -488,7 +488,7 @@ static val strlist_out_put_string(val stream, val str) if (zerop(length)) break; - put_string(strstream, sub_str(str, nil, span_to_newline)); + put_string(sub_str(str, nil, span_to_newline), strstream); if (equal(span_to_newline, length)) break; @@ -513,7 +513,7 @@ static val strlist_out_put_char(val stream, val ch) push(get_string_from_stream(strstream), &lines); strstream = make_string_output_stream(); } else { - put_char(strstream, ch); + put_char(ch, strstream); } *car_l(cell) = lines; @@ -705,6 +705,9 @@ val close_stream(val stream, val throw_on_error) val get_line(val stream) { + if (!stream) + stream = std_input; + type_check (stream, COBJ); type_assert (stream->co.cls == stream_s, (lit("~a is not a stream"), stream, nao)); @@ -717,6 +720,9 @@ val get_line(val stream) val get_char(val stream) { + if (!stream) + stream = std_input; + type_check (stream, COBJ); type_assert (stream->co.cls == stream_s, (lit("~a is not a stream"), stream, nao)); @@ -729,6 +735,9 @@ val get_char(val stream) val get_byte(val stream) { + if (!stream) + stream = std_input; + type_check (stream, COBJ); type_assert (stream->co.cls == stream_s, (lit("~a is not a stream"), stream, nao)); @@ -790,33 +799,33 @@ static val vformat_num(val stream, const char *str, if (!left) for (i = 0; i < slack; i++) - if (!put_char(stream, chr(' '))) + if (!put_char(chr(' '), stream)) return nil; if (!zeropad) for (i = 0; i < padlen; i++) - if (!put_char(stream, chr(' '))) + if (!put_char(chr(' '), stream)) return nil; if (sign_char) { - put_char(stream, chr(sign_char)); + put_char(chr(sign_char), stream); str++; } else if (sign) { - put_char(stream, chr(sign)); + put_char(chr(sign), stream); } if (zeropad) for (i = 0; i < padlen; i++) - if (!put_char(stream, chr('0'))) + if (!put_char(chr('0'), stream)) return nil; while (*str) - if (!put_char(stream, chr(*str++))) + if (!put_char(chr(*str++), stream)) return nil; if (left) for (i = 0; i < slack; i++) - if (!put_char(stream, chr(' '))) + if (!put_char(chr(' '), stream)) return nil; return t; @@ -833,16 +842,16 @@ static val vformat_str(val stream, val str, int width, int left, if (!left) for (i = 0; i < slack; i++) - if (!put_char(stream, chr(' '))) + if (!put_char(chr(' '), stream)) return nil; for (i = 0; i < truelen; i++) - if (!put_char(stream, chr(cstr[i]))) + if (!put_char(chr(cstr[i]), stream)) return nil; if (left) for (i = 0; i < slack; i++) - if (!put_char(stream, chr(' '))) + if (!put_char(chr(' '), stream)) return nil; return t; @@ -883,14 +892,14 @@ val vformat(val stream, val fmtstr, va_list vl) digits = 0; continue; default: - put_char(stream, chr(ch)); + put_char(chr(ch), stream); continue; } break; case vf_width: switch (ch) { case '~': - put_char(stream, chr('~')); + put_char(chr('~'), stream); state = vf_init; continue; case '<': @@ -1146,8 +1155,11 @@ val formatv(val stream, val string, val args) abort(); } -val put_string(val stream, val string) +val put_string(val string, val stream) { + if (!stream) + stream = std_output; + type_check (stream, COBJ); type_assert (stream->co.cls == stream_s, (lit("~a is not a stream"), stream, nao)); @@ -1158,8 +1170,11 @@ val put_string(val stream, val string) } } -val put_char(val stream, val ch) +val put_char(val ch, val stream) { + if (!stream) + stream = std_output; + type_check (stream, COBJ); type_assert (stream->co.cls == stream_s, (lit("~a is not a stream"), stream, nao)); @@ -1170,9 +1185,9 @@ val put_char(val stream, val ch) } } -val put_line(val stream, val string) +val put_line(val string, val stream) { - return (put_string(stream, string), put_char(stream, chr('\n'))); + return (put_string(string, stream), put_char(chr('\n'), stream)); } val flush_stream(val stream) @@ -45,9 +45,9 @@ val vformat(val stream, val string, va_list); val vformat_to_string(val string, va_list); val format(val stream, val string, ...); val formatv(val stream, val string, val args); -val put_string(val stream, val string); -val put_line(val stream, val string); -val put_char(val stream, val ch); +val put_string(val string, val stream); +val put_line(val string, val stream); +val put_char(val ch, val stream); val flush_stream(val stream); val open_directory(val path); val open_file(val path, val mode_str); @@ -4606,6 +4606,11 @@ The dotted notation can be used to write a function that accepts a variable number of arguments. To write a function that accepts variable arguments only, with no required arguments, use a single symbol. +The keyword symbol : can appear in the parameter list. It is not an argument, +but a separator between required parameters and optional parameters. +When the function is called, optional parameter for which arguments +are not supplied take on the value nil. + Functions created by lambda capture the surrounding variable bindings. @@ -4628,6 +4633,11 @@ Variadic funcion: (lambda args (list 'my-list-of-arguments args)) +Optional arguments: + + [(lambda (x : y) (list x y)) 1] -> (1 nil) + [(lambda (x : y) (list x y)) 1 2] -> (1 2) + .SS Operator op .TP @@ -4855,11 +4865,13 @@ Syntax: Description: The defun operator introduces a new function in the global function namespace. -The function is similar to a lambda, except that <body-form>-s are surrounded -by a named block called nil. The name of this block is the same as the name of -the function, making it possible to terminate the function and return a -value using (return-from <name> <value>). For more information, see the -definition of the block operator. +The function is similar to a lambda, and has the same parameter syntax +and semantics as the lambda operator. + +Unlike in lambda, the <body-form>-s of a defun are surrounded by a block. +The name of this block is the same as the name of the function, making it +possible to terminate the function and return a value using (return-from <name> +<value>). For more information, see the definition of the block operator. A function may call itself by name, allowing for recursion. @@ -6430,7 +6442,7 @@ Certain object types have a custom equal function. .SS Functions search-regex and match-regex -.SS Function make-hash +.SS Functions make-hash, hash .SS Function sethash @@ -56,7 +56,7 @@ val spec_file_str; static mem_t *oom_realloc_handler(mem_t *old, size_t size) { format(std_error, lit("~a: out of memory\n"), prog_string, nao); - put_line(std_error, lit("false")); + put_line(lit("false"), std_error); abort(); } @@ -45,7 +45,7 @@ syn keyword txl_keyword contained all none eq eql equal + - * abs trunc mod syn keyword txl_keyword contained expt exptmod sqrt gcd fixnump bignump syn keyword txl_keyword contained numberp zerop evenp oddp > syn keyword txl_keyword contained < >= <= max min search-regex match-regex -syn keyword txl_keyword contained make-hash gethash sethash pushhash remhash +syn keyword txl_keyword contained make-hash hash gethash sethash pushhash remhash syn keyword txl_keyword contained hash-count get-hash-userdata set-hash-userdata hashp maphash syn keyword txl_keyword contained hash-eql hash-equal eval *stdout* *stdin* syn keyword txl_keyword contained *stderr* format print pprint tostring tostringp @@ -79,7 +79,7 @@ syn keyword txl_keyword contained sub ref replace syn keyword txl_keyword contained symbol-function func-get-form func-get-env syn keyword txl_keyword contained functionp interp-fun-p *random-state* syn keyword txl_keyword contained make-random-state random-state-p -syn keyword txl_keyword contained random-fixnum random +syn keyword txl_keyword contained random-fixnum random rand syn keyword txl_keyword contained range range* generate repeat force syn keyword txl_keyword contained throw throwf error match-fun @@ -269,7 +269,7 @@ val uw_throw(val sym, val exception) if (uw_exception_subtype_p(sym, query_error_s) || uw_exception_subtype_p(sym, file_error_s)) { if (!output_produced) - put_line(std_output, lit("false")); + put_line(lit("false"), std_output); exit(EXIT_FAILURE); } abort(); |