summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-02-21 06:07:57 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-02-21 06:07:57 -0800
commit563b6367a572bc50f8fbec2aeff255c258407862 (patch)
treedc907e344c6e3526f1215a1cd5ab2b018b32d74d
parent3f93ddf1acc8b6d3647dec31e7329987d452daa5 (diff)
downloadtxr-563b6367a572bc50f8fbec2aeff255c258407862.tar.gz
txr-563b6367a572bc50f8fbec2aeff255c258407862.tar.bz2
txr-563b6367a572bc50f8fbec2aeff255c258407862.zip
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.
-rw-r--r--ChangeLog21
-rw-r--r--eval.c29
-rw-r--r--eval.h2
-rw-r--r--parser.l6
-rw-r--r--unwind.c10
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 <kaz@kylheku.com>
+
+ 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 <kaz@kylheku.com>
* 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,