diff options
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | lib.c | 24 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | match.c | 95 |
4 files changed, 94 insertions, 50 deletions
@@ -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 @@ -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) { @@ -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); @@ -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)); } } |