summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-07-14 06:20:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-07-14 06:20:48 -0700
commit5b71846a6561d20a0c954095f92cf125674ea8f1 (patch)
tree394abf5b590046f4a5d4053d633ceeb9e2a8520b
parent974532041c1eaeb55c9fcb4c395e4da5f19a4773 (diff)
downloadtxr-5b71846a6561d20a0c954095f92cf125674ea8f1.tar.gz
txr-5b71846a6561d20a0c954095f92cf125674ea8f1.tar.bz2
txr-5b71846a6561d20a0c954095f92cf125674ea8f1.zip
bugfix: spurious warnings issued against lisp1 eval.
Repro test cases for this: A: (progn (defun f ()) [f]). This emits a warning against the [f] usage, even though there is a tentative definition of f as a function. B: (progn (defun g () [f]) (defun f ())). Emits a warning against [f] usage which is not purged by the evaluation of the later definition. Both problems are related to the separation of deferred warnings into the tag namespaces: symbols and functions. When [f] is being expanded, the deferred warning is put into the variable namespace. So it doesn't match a tentative def in the function namespace which would otherwise suppress it. A subsequent function definition only purges the warning for the function space. We introduce a third space, the "symbol space". Lisp-1 deferred warnings are introduced against this namespace and both variable and function definitions purge deferred warnings from that namespace also, in addition to their respective proper namespace. This solves problem B. Problem A is solved by checking, when [f] is expanded, for tentative definitions of f in both the variable and function tag space. Note that test case B still warns when entered into the listener, because the listener dumps deferred warnings prior to evaluation, thus prior to evaluating (defun f ()). * eval.c (op_defvarl, op_defun): Purge deferred warnings from the sym tag namespace also. (expand_lisp1): Do not emit the deferred warning for a nonexistent name if it has a tentative definition either as a function or variable. When emitting the deferred warning, use the sym namespace.
-rw-r--r--eval.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index 679b12aa..27aca963 100644
--- a/eval.c
+++ b/eval.c
@@ -1777,6 +1777,7 @@ static val op_defvarl(val form, val env)
remhash(top_smb, sym);
sethash(top_vb, sym, cons(sym, value));
uw_purge_deferred_warning(cons(var_s, sym));
+ uw_purge_deferred_warning(cons(sym_s, sym));
}
return sym;
@@ -1827,6 +1828,7 @@ static val op_defun(val form, val env)
if (eval_initing)
sethash(builtin, name, defun_s);
uw_purge_deferred_warning(cons(fun_s, name));
+ uw_purge_deferred_warning(cons(sym_s, name));
return name;
} else if (car(name) == meth_s) {
val binding = lookup_fun(nil, intern(lit("defmeth"), system_package));
@@ -2986,10 +2988,14 @@ tail:
form = rlcp_tree(symac, form);
goto tail;
}
- if (!lookup_var(menv, form) && !lookup_fun(menv, form))
+ if (!lookup_var(menv, form) && !lookup_fun(menv, form) &&
+ !uw_tentative_def_exists(cons(var_s, form)) &&
+ !uw_tentative_def_exists(cons(fun_s, form)))
+ {
eval_defr_warn(last_form_expanded,
- cons(var_s, form),
+ cons(sym_s, form),
lit("unbound variable/function ~s"), form, nao);
+ }
return form;
}