From 563b6367a572bc50f8fbec2aeff255c258407862 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sat, 21 Feb 2015 06:07:57 -0800 Subject: Improved error reporting, particularly for macro expansion. * eval.c (last_form_expanded): New variable. (do_expand): New static function; contains previous expand function. (expand): Becomes a wrapper for do_expand, with re-entry counting. (eval_init): GC-protect last_form_expanded. * eval.h (last_form_expanded): Declared. * parser.l (regex_parse, lisp_parse): Just use a simple word for the name of the regex or string parse location, not the entire expression itself. * unwind.c (uw_throw): Check whether expansion was going on when the unhandled exception was thrown and print additional information. --- ChangeLog | 21 +++++++++++++++++++++ eval.c | 29 ++++++++++++++++++++++++++--- eval.h | 2 +- parser.l | 6 ++---- unwind.c | 10 ++++++++-- 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e4351d31..ab51ffc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2015-02-21 Kaz Kylheku + + Improved error reporting, particularly for macro expansion. + + * eval.c (last_form_expanded): New variable. + (do_expand): New static function; contains previous expand + function. + (expand): Becomes a wrapper for do_expand, with re-entry + counting. + (eval_init): GC-protect last_form_expanded. + + * eval.h (last_form_expanded): Declared. + + * parser.l (regex_parse, lisp_parse): Just use a simple word for + the name of the regex or string parse location, not the entire + expression itself. + + * unwind.c (uw_throw): Check whether expansion was going on + when the unhandled exception was thrown and print additional + information. + 2015-02-20 Kaz Kylheku * regex.c (match_regex_right): Bugfix: zero length matches diff --git a/eval.c b/eval.c index 5721aa85..dce7e949 100644 --- a/eval.c +++ b/eval.c @@ -87,7 +87,7 @@ val opip_s, oand_s, chain_s, chand_s; val special_s, whole_k, symacro_k, fun_k; -val last_form_evaled; +val last_form_evaled, last_form_expanded; val call_f; @@ -2806,7 +2806,7 @@ static val expand_save_specials(val form, val specials) return rlcp(cons(with_saved_vars_s, cons(form, nil)), form); } -val expand(val form, val menv) +static val do_expand(val form, val menv) { val macro = nil; @@ -3023,6 +3023,28 @@ tail: } } +val expand(val form, val menv) +{ + val ret = nil; + static int reentry_count; + + uw_simple_catch_begin; + + reentry_count++; + + last_form_expanded = form; + ret = do_expand(form, menv); + + uw_unwind { + if (--reentry_count == 0) + last_form_expanded = nil; + } + + uw_catch_end; + + return ret; +} + static val macro_form_p(val form, val menv) { menv = default_bool_arg(menv); @@ -3675,7 +3697,8 @@ static val merge_wrap(val seq1, val seq2, val lessfun, val keyfun) void eval_init(void) { protect(&top_vb, &top_fb, &top_mb, &top_smb, &special, &dyn_env, - &op_table, &last_form_evaled, &call_f, convert(val *, 0)); + &op_table, &last_form_evaled, &last_form_expanded, + &call_f, convert(val *, 0)); top_fb = make_hash(t, nil, nil); top_vb = make_hash(t, nil, nil); top_mb = make_hash(t, nil, nil); diff --git a/eval.h b/eval.h index b30e6615..f027de1a 100644 --- a/eval.h +++ b/eval.h @@ -27,7 +27,7 @@ extern val dwim_s, lambda_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; +extern val last_form_evaled, last_form_expanded; val make_env(val fbindings, val vbindings, val up_env); val env_fbind(val env, val sym, val fun); diff --git a/parser.l b/parser.l index 6d47078b..0c3ba64e 100644 --- a/parser.l +++ b/parser.l @@ -985,9 +985,7 @@ val regex_parse(val string, val error_stream) { int gc = gc_state(0); - val name = if3(std_error != std_null, - format(nil, lit("regex --> ~a"), string, nao), - lit("")); + val name = if3(std_error != std_null, lit("regex"), lit("")); parse(stream, name, &parser); gc_state(gc); } @@ -1004,7 +1002,7 @@ val lisp_parse(val source_in, val error_stream, val error_return_val) or2(source, std_input)); val secret_token_stream = make_string_byte_input_stream(lit("@\x01" "E")); val name = if3(stringp(source), - format(nil, lit("expr --> ~a"), source, nao), + lit("string"), stream_get_prop(input_stream, name_k)); val stream = make_catenated_stream(list(secret_token_stream, input_stream, nao)); val saved_dyn = dyn_env; diff --git a/unwind.c b/unwind.c index 5d358e42..51c2dae0 100644 --- a/unwind.c +++ b/unwind.c @@ -315,12 +315,18 @@ val uw_throw(val sym, val args) val msg_or_args = if3(is_msg, car(args), args); val info = if2(source_loc(last_form_evaled), source_loc_str(last_form_evaled)); + val ex_info = if2(source_loc(last_form_expanded), + source_loc_str(last_form_expanded)); 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, lit("~a: possibly triggered at ~a by form ~s\n"), + prog_string, info, last_form_evaled, nao); + + if (ex_info) + format(std_error, lit("~a: during expansion at ~a of form ~s\n"), + prog_string, ex_info, last_form_expanded, nao); format(std_error, if3(is_msg, -- cgit v1.2.3