summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-11-06 19:37:06 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-11-06 19:37:06 -0800
commite84af1abfba77bc0d2707cae21e6a44b32de1a3c (patch)
treec837f7bbe98a0e6ed7e40d46fcca69999ba49bdf /match.c
parent687fd6ab7031aa573cbcd1b3ae624eb02530a25c (diff)
downloadtxr-e84af1abfba77bc0d2707cae21e6a44b32de1a3c.tar.gz
txr-e84af1abfba77bc0d2707cae21e6a44b32de1a3c.tar.bz2
txr-e84af1abfba77bc0d2707cae21e6a44b32de1a3c.zip
Task #11581 & bugfix.
* match.c (noval_s): New symbol variable. (vars_to_bindings): Use a default value of noval_s to indicate a required variable, rather than nil, which would not allow an optional variable with a default value of nil. (h_coll, v_collect): Check default value against noval_s, rather than nil. (v_gather): Support :vars keyword. (syms_init): Initialize new symbol variable. * txr.1: Documented gather's :vars parameter.
Diffstat (limited to 'match.c')
-rw-r--r--match.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/match.c b/match.c
index 066dbb23..e4ff0e22 100644
--- a/match.c
+++ b/match.c
@@ -58,6 +58,8 @@ val append_k, into_k, var_k, list_k, string_k, env_k;
val filter_s;
+val noval_s;
+
static val h_directive_table, v_directive_table;
static void debugf(val fmt, ...)
@@ -338,7 +340,7 @@ static val vars_to_bindings(val lineno, val vars, val bindings)
for (iter = vars; iter; iter = cdr(iter)) {
val item = car(iter);
if (bindable(item)) {
- list_collect (tail, cons(item, nil));
+ list_collect (tail, cons(item, noval_s));
} else if (consp(item) && bindable(first(item))) {
list_collect (tail, cons(first(item),
cdr(eval_form(lineno, second(item), bindings))));
@@ -715,7 +717,7 @@ static val h_coll(match_line_ctx c, match_line_ctx *cout)
val exists = assoc(new_bindings, var);
if (!exists) {
- if (!dfl)
+ if (dfl == noval_s)
sem_error(c.spec_lineno, lit("coll failed to bind ~a"),
var, nao);
else
@@ -1925,6 +1927,8 @@ static val v_gather(match_files_ctx *c)
{
spec_bind (specline, spec_linenum, first_spec, c->spec);
val specs = copy_list(second(first_spec));
+ val args = third(first_spec);
+ val vars = vars_to_bindings(spec_linenum, getplist(args, vars_k), c->bindings);
while (specs && c->data) {
list_collect_decl (new_specs, ptail);
@@ -1971,6 +1975,25 @@ static val v_gather(match_files_ctx *c)
}
}
+ if (vars) {
+ val iter;
+
+ for (iter = vars; iter != nil; iter = cdr(iter)) {
+ cons_bind (var, dfl_val, car(iter));
+ if (!assoc(c->bindings, var)) {
+ if (dfl_val == noval_s) {
+ debuglf(spec_linenum, lit("gather failed to match some required vars"), nao);
+ return nil;
+ } else {
+ c->bindings = acons(c->bindings, var, dfl_val);
+ }
+ }
+ }
+
+ debuglf(spec_linenum, lit("gather matched all required vars"), nao);
+ return next_spec_k;
+ }
+
if (specs) {
debuglf(spec_linenum, lit("gather failed to match some specs:"), nao);
debuglf(spec_linenum, lit("~s"), specs, nao);
@@ -2071,7 +2094,7 @@ static val v_collect(match_files_ctx *c)
val exists = assoc(new_bindings, var);
if (!exists) {
- if (!dfl)
+ if (dfl == noval_s)
sem_error(spec_linenum, lit("collect failed to bind ~a"),
var, nao);
else
@@ -2950,6 +2973,7 @@ static void syms_init(void)
env_k = intern(lit("env"), keyword_package);
filter_s = intern(lit("filter"), user_package);
+ noval_s = intern(lit("noval"), system_package);
}
static void dir_tables_init(void)