summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--lib.c24
-rw-r--r--lib.h2
-rw-r--r--match.c95
4 files changed, 94 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index a8714a2c..d5540534 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2011-10-06 Kaz Kylheku <kaz@kylheku.com>
+
+ * lib.c (funcall3, curry_123_2): New functions.
+ (do_curry_123_2): New static function.
+
+ * lib.h (funcall3, curry_123_2): Declared.
+
+ * match.c (subst_vars): Bugfix: throw error on unbound variable instead
+ of ignoring the situation. This bug caused unbound variables in
+ quasiliterals to be silently ignored.
+ (eval_form): Function changed to three argument form, so that
+ it takes a line number for reporting errors. Restructured to catch
+ the new unbound variable exception from subst_vars, and re-throw
+ it with a line number. Also, throws exception now instead of returning
+ nil if itself it detets an unbound variable. Uses of eval_form
+ no longer have to test the return value for nil, but just assume
+ it worked.
+ (match_lines): Currying calls to eval form updated to use
+ curry_123_2. Test of eval return value eliminated. In function
+ calls, eval isn't used for reducing symbol arguments to values,
+ because it now throws in the unbound case, and it's not worth
+ setting up a catch for this. Instead, assoc is used directly.
+
2011-10-05 Kaz Kylheku <kaz@kylheku.com>
* match.c (match_files): In function calls, the deletion of
diff --git a/lib.c b/lib.c
index 52208ce6..b53e8fd3 100644
--- a/lib.c
+++ b/lib.c
@@ -1446,6 +1446,21 @@ val funcall2(val fun, val arg1, val arg2)
}
}
+val funcall3(val fun, val arg1, val arg2, val arg3)
+{
+ type_check(fun, FUN);
+
+ switch (fun->f.functype) {
+ case F3:
+ return fun->f.f.f3(fun->f.env, arg1, arg2, arg3);
+ case N3:
+ return fun->f.f.n3(arg1, arg2, arg3);
+ default:
+ uw_throwf(error_s, lit("funcall3: wrong number of arguments"));
+ }
+}
+
+
val reduce_left(val fun, val list, val init, val key)
{
if (!key)
@@ -1477,6 +1492,15 @@ val bind2other(val fun2, val arg2)
return func_f1(cons(fun2, arg2), do_bind2other);
}
+static val do_curry_123_2(val fcons, val arg2)
+{
+ return funcall3(car(fcons), car(cdr(fcons)), arg2, cdr(cdr(fcons)));
+}
+
+val curry_123_2(val fun3, val arg1, val arg3)
+{
+ return func_f1(cons(fun3, cons(arg1, arg3)), do_curry_123_2);
+}
static val do_chain(val fun1_list, val arg)
{
diff --git a/lib.h b/lib.h
index 0d55701f..302f8b35 100644
--- a/lib.h
+++ b/lib.h
@@ -352,9 +352,11 @@ val apply(val fun, val arglist);
val funcall(val fun);
val funcall1(val fun, val arg);
val funcall2(val fun, val arg1, val arg2);
+val funcall3(val fun, val arg1, val arg2, val arg3);
val reduce_left(val fun, val list, val init, val key);
val bind2(val fun2, val arg);
val bind2other(val fun2, val arg2);
+val curry_123_2(val fun3, val arg1, val arg3);
val chain(val first_fun, ...);
val andf(val first_fun, ...);
val vector(val alloc);
diff --git a/match.c b/match.c
index 94ede32d..a00288e5 100644
--- a/match.c
+++ b/match.c
@@ -790,7 +790,8 @@ static val subst_vars(val spec, val bindings, val filter)
spec = cons(filter_string(filter, cdr(pair)), rest(spec));
continue;
}
- /* TODO: handle unbound variable */
+ uw_throwf(query_error_s, lit("unbound variable ~a"),
+ sym, nao);
} else if (first(elem) == quasi_s) {
val nested = subst_vars(rest(elem), bindings, filter);
list_collect_append(iter, nested);
@@ -811,29 +812,44 @@ static val subst_vars(val spec, val bindings, val filter)
return out;
}
-static val eval_form(val form, val bindings)
+static val eval_form(val lineno, val form, val bindings)
{
- if (!form) {
- return cons(t, form);
- } else if (bindable(form)) {
- return assoc(bindings, form);
- } else if (consp(form)) {
- if (car(form) == quasi_s) {
- return cons(t, cat_str(subst_vars(rest(form), bindings, nil), nil));
- } else if (regexp(car(form))) {
- return cons(t, form);
+ val ret = nil;
+
+ uw_catch_begin (cons(query_error_s, nil), exc_sym, exc);
+ {
+ if (!form) {
+ ret = cons(t, form);
+ } else if (bindable(form)) {
+ ret = assoc(bindings, form);
+ } else if (consp(form)) {
+ if (car(form) == quasi_s) {
+ ret = cons(t, cat_str(subst_vars(rest(form), bindings, nil), nil));
+ } else if (regexp(car(form))) {
+ ret = cons(t, form);
+ } else {
+ val subforms = mapcar(curry_123_2(func_n3(eval_form),
+ lineno, bindings), form);
+
+ if (all_satisfy(subforms, identity_f, nil))
+ ret = cons(t, mapcar(func_n1(cdr), subforms));
+ }
+ } else if (stringp(form)) {
+ ret = cons(t, form);
} else {
- val subforms = mapcar(bind2other(func_n2(eval_form), bindings), form);
+ ret = cons(t, form);
+ }
- if (all_satisfy(subforms, identity_f, nil))
- return cons(t, mapcar(func_n1(cdr), subforms));
- return nil;
+ uw_catch (exc_sym, exc) {
+ sem_error(lineno, lit("~a"), exc, nao);
}
- } if (stringp(form)) {
- return cons(t, form);
}
+ uw_catch_end;
+
+ if (!ret)
+ sem_error(lineno, lit("unbound variable in form ~s"), form, nao);
- return cons(t, form);
+ return ret;
}
enum fpip_close { fpip_fclose, fpip_pclose, fpip_closedir };
@@ -1225,8 +1241,8 @@ repeat_spec_same_data:
} else if (sym == freeform_s) {
val args = rest(first_spec);
val vals = mapcar(func_n1(cdr),
- mapcar(bind2other(func_n2(eval_form),
- bindings), args));
+ mapcar(curry_123_2(func_n3(eval_form),
+ spec_linenum, bindings), args));
if ((spec = rest(spec)) == nil) {
sem_error(spec_linenum,
@@ -1324,13 +1340,9 @@ repeat_spec_same_data:
}
{
- val eval = eval_form(arg, bindings);
+ val eval = eval_form(spec_linenum, arg, bindings);
val str = cdr(eval);
- if (!eval)
- sem_error(spec_linenum, lit("next: unbound variable in form ~a"),
- first(source), nao);
-
if (eq(second(source), nothrow_k)) {
if (str) {
files = cons(cons(nothrow_k, str), files);
@@ -1685,11 +1697,7 @@ repeat_spec_same_data:
val arg = first(args);
if (arg) {
- val arg_eval = eval_form(arg, bindings);
-
- if (!arg_eval)
- sem_error(spec_linenum, lit("~a: unbound variable in form ~s"),
- sym, arg, nao);
+ val arg_eval = eval_form(spec_linenum, arg, bindings);
if (merged)
merged = weird_merge(merged, cdr(arg_eval));
@@ -1708,11 +1716,7 @@ repeat_spec_same_data:
val args = rest(first_spec);
val pattern = first(args);
val form = second(args);
- val val = eval_form(form, bindings);
-
- if (!val)
- sem_error(spec_linenum, lit("bind: unbound variable on right side"),
- nao);
+ val val = eval_form(spec_linenum, form, bindings);
bindings = dest_bind(bindings, pattern, cdr(val));
@@ -1763,12 +1767,7 @@ repeat_spec_same_data:
sem_error(spec_linenum, lit("material after :nothrow in output"), nao);
} else if (!keywordp(first(dest_spec))) {
val form = first(dest_spec);
- val val = eval_form(form, bindings);
-
- if (!val)
- sem_error(spec_linenum,
- lit("output: unbound variable in form ~a"), form, nao);
-
+ val val = eval_form(spec_linenum, form, bindings);
dest = or2(cdr(val), dest);
pop(&dest_spec);
}
@@ -1978,8 +1977,8 @@ repeat_spec_same_data:
sem_error(spec_linenum, lit("throw: ~a is not a type symbol"),
type, nao);
{
- val values = mapcar(bind2other(func_n2(eval_form), bindings),
- args);
+ val values = mapcar(curry_123_2(func_n3(eval_form),
+ spec_linenum, bindings), args);
uw_throw(type, values);
}
} else if (sym == deffilter_s) {
@@ -2039,8 +2038,8 @@ repeat_spec_same_data:
val param = car(piter);
val arg = car(aiter);
- if (arg && symbolp(arg)) {
- val val = eval_form(arg, bindings);
+ if (arg && bindable(arg)) {
+ val val = assoc(bindings, arg);
if (val) {
bindings_cp = acons_new(bindings_cp,
param,
@@ -2050,11 +2049,7 @@ repeat_spec_same_data:
ub_p_a_pairs = cons(cons(param, arg), ub_p_a_pairs);
}
} else {
- val val = eval_form(arg, bindings);
- if (!val)
- sem_error(spec_linenum,
- lit("unbound variable in function argument form"),
- nao);
+ val val = eval_form(spec_linenum, arg, bindings);
bindings_cp = acons_new(bindings_cp, param, cdr(val));
}
}