summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2012-02-21 18:13:52 -0800
committerKaz Kylheku <kaz@kylheku.com>2012-02-21 18:13:52 -0800
commit72d59307630fd1bd9ee1c06cdad4cfb634bc9a3a (patch)
tree2232b5a5374c92d566f087f2bc5e5067a5fb8fd4
parent216c446da541d2a2e68c57feee04bafce00013e5 (diff)
downloadtxr-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--ChangeLog77
-rw-r--r--debug.c8
-rw-r--r--eval.c145
-rw-r--r--gc.c2
-rw-r--r--hash.c13
-rw-r--r--hash.h3
-rw-r--r--lib.c255
-rw-r--r--lib.h19
-rw-r--r--match.c26
-rw-r--r--parser.l9
-rw-r--r--rand.c5
-rw-r--r--rand.h1
-rw-r--r--stream.c51
-rw-r--r--stream.h6
-rw-r--r--txr.124
-rw-r--r--txr.c2
-rw-r--r--txr.vim4
-rw-r--r--unwind.c2
18 files changed, 449 insertions, 203 deletions
diff --git a/ChangeLog b/ChangeLog
index b523e847..aee098cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/debug.c b/debug.c
index 55e7fb4e..175dc5b7 100644
--- a/debug.c
+++ b/debug.c
@@ -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))
diff --git a/eval.c b/eval.c
index 9380df06..864ac82f 100644
--- a/eval.c
+++ b/eval.c
@@ -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));
diff --git a/gc.c b/gc.c
index a01ce794..569a1abc 100644
--- a/gc.c
+++ b/gc.c
@@ -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);
diff --git a/hash.c b/hash.c
index e8f5bb1b..32868569 100644
--- a/hash.c
+++ b/hash.c
@@ -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);
}
diff --git a/hash.h b/hash.h
index c425aabf..5ad73c3b 100644
--- a/hash.h
+++ b/hash.h
@@ -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);
diff --git a/lib.c b/lib.c
index fe433d3a..00ce2549 100644
--- a/lib.c
+++ b/lib.c
@@ -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);
}
/*
diff --git a/lib.h b/lib.h
index e75c5acc..1930a765 100644
--- a/lib.h
+++ b/lib.h
@@ -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);
diff --git a/match.c b/match.c
index 3735b07a..9028cd81 100644
--- a/match.c
+++ b/match.c
@@ -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;
diff --git a/parser.l b/parser.l
index 279cb7ec..d2745c99 100644
--- a/parser.l
+++ b/parser.l
@@ -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();
diff --git a/rand.c b/rand.c
index b28398ba..ca78c8ad 100644
--- a/rand.c
+++ b/rand.c
@@ -241,6 +241,11 @@ invalid:
modulus, nao);
}
+val rand(val modulus, val state)
+{
+ return random(state, modulus);
+}
+
void rand_init(void)
{
prot1(&random_state);
diff --git a/rand.h b/rand.h
index 7426b461..9ff55396 100644
--- a/rand.h
+++ b/rand.h
@@ -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);
diff --git a/stream.c b/stream.c
index 64380b87..dffc8e25 100644
--- a/stream.c
+++ b/stream.c
@@ -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)
diff --git a/stream.h b/stream.h
index 4cb7f923..207d2acb 100644
--- a/stream.h
+++ b/stream.h
@@ -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);
diff --git a/txr.1 b/txr.1
index 636c8aba..25e6d8b6 100644
--- a/txr.1
+++ b/txr.1
@@ -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
diff --git a/txr.c b/txr.c
index d4c7ef28..084d20a3 100644
--- a/txr.c
+++ b/txr.c
@@ -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();
}
diff --git a/txr.vim b/txr.vim
index 7ba1c452..92cec943 100644
--- a/txr.vim
+++ b/txr.vim
@@ -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
diff --git a/unwind.c b/unwind.c
index ac4bb79d..b2ba9e2c 100644
--- a/unwind.c
+++ b/unwind.c
@@ -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();