diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-16 01:52:56 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-16 01:52:56 -0800 |
commit | 83778347170b3168bbfd5a87bad1eb12700f5cd0 (patch) | |
tree | 9af5a9c884ab7834519e6650022d763f8415bb62 | |
parent | b68fb2aad15663edfe7c3671c97bd85bc531c565 (diff) | |
download | txr-83778347170b3168bbfd5a87bad1eb12700f5cd0.tar.gz txr-83778347170b3168bbfd5a87bad1eb12700f5cd0.tar.bz2 txr-83778347170b3168bbfd5a87bad1eb12700f5cd0.zip |
In the spirit of the previous hack, here is another hack to
alleviate a long-standing pain: when an exception happens in
TXR's library somewhere, the program dies without leaving
a clue about what code was being evaluated when that happened.
What we can do is have the evaluator publish the most recent
compound form it has processed by stashing it in a variable.
Then when an unhandled exception occurs, we can peek at that
and try to pull out source location info.
* eval.c (last_form_evaled): New variable.
(do_eval): When evaluating a compound form, stash it in
last_form_evaled.
(eval_init): Protect last_form_evaled from gc.
* eval.h (last_form_evaled): Declared.
(eval_error_s): Existing variable declared.
* unwind.c: Has to include "eval.h" for the above variable
and "parser.h" for the source_loc function.
(uw_throw): When an exception is unhandled, if
last_form_evaled has source info, add it to the diagnostic.
But not if the exception is eval-error; because errors from
the evaluators already have the info.
-rw-r--r-- | ChangeLog | 26 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | eval.h | 2 | ||||
-rw-r--r-- | unwind.c | 10 |
4 files changed, 43 insertions, 1 deletions
@@ -1,5 +1,31 @@ 2014-02-16 Kaz Kylheku <kaz@kylheku.com> + In the spirit of the previous hack, here is another hack to + alleviate a long-standing pain: when an exception happens in + TXR's library somewhere, the program dies without leaving + a clue about what code was being evaluated when that happened. + What we can do is have the evaluator publish the most recent + compound form it has processed by stashing it in a variable. + Then when an unhandled exception occurs, we can peek at that + and try to pull out source location info. + + * eval.c (last_form_evaled): New variable. + (do_eval): When evaluating a compound form, stash it in + last_form_evaled. + (eval_init): Protect last_form_evaled from gc. + + * eval.h (last_form_evaled): Declared. + (eval_error_s): Existing variable declared. + + * unwind.c: Has to include "eval.h" for the above variable + and "parser.h" for the source_loc function. + (uw_throw): When an exception is unhandled, if + last_form_evaled has source info, add it to the diagnostic. + But not if the exception is eval-error; because errors from + the evaluators already have the info. + +2014-02-16 Kaz Kylheku <kaz@kylheku.com> + Nice idea: how about a function which walks the tree structure and back-fills some missing source code location info. We apply this to macro expansions. If some error occurs in expanded code, this way it @@ -91,6 +91,8 @@ val macro_time_s; val whole_k, env_k; +val last_form_evaled; + val make_env(val vbindings, val fbindings, val up_env) { val env = make_obj(); @@ -717,6 +719,8 @@ static val do_eval(val form, val env, val ctx_form, } else if (consp(form)) { val oper = car(form); + last_form_evaled = form; + if (regexp(oper)) debug_return (oper); @@ -2502,7 +2506,7 @@ static val and_fun(val vals) void eval_init(void) { - protect(&top_vb, &top_fb, &top_mb, &op_table, (val *) 0); + protect(&top_vb, &top_fb, &top_mb, &op_table, &last_form_evaled, (val *) 0); top_fb = make_hash(t, nil, nil); top_vb = make_hash(t, nil, nil); top_mb = make_hash(t, nil, nil); @@ -26,6 +26,8 @@ extern val dwim_s, vector_lit_s, vector_list_s; extern val hash_lit_s, hash_construct_s; +extern val eval_error_s; +extern val last_form_evaled; val make_env(val fbindings, val vbindings, val up_env); val env_fbind(val env, val sym, val fun); @@ -38,6 +38,8 @@ #include "stream.h" #include "txr.h" #include "signal.h" +#include "eval.h" +#include "parser.h" #include "unwind.h" static uw_frame_t *uw_stack; @@ -275,10 +277,18 @@ val uw_throw(val sym, val exception) if (opt_loglevel >= 1) { val s = stringp(exception); + val info = if2(source_loc(last_form_evaled), + source_loc_str(last_form_evaled)); format(std_error, lit("~a: unhandled exception of type ~a:\n"), prog_string, sym, nao); + + if (info && sym != eval_error_s) + format(std_error, lit("~a: possibly triggered by ~a\n"), + prog_string, info, nao); + format(std_error, s ? lit("~a: ~a\n") : lit("~a: ~s\n"), prog_string, exception, nao); + } if (uw_exception_subtype_p(sym, query_error_s) || uw_exception_subtype_p(sym, file_error_s)) { |