diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-11-06 19:37:06 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-11-06 19:37:06 -0800 |
commit | e84af1abfba77bc0d2707cae21e6a44b32de1a3c (patch) | |
tree | c837f7bbe98a0e6ed7e40d46fcca69999ba49bdf /match.c | |
parent | 687fd6ab7031aa573cbcd1b3ae624eb02530a25c (diff) | |
download | txr-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.c | 30 |
1 files changed, 27 insertions, 3 deletions
@@ -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) |