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
commitf7418016db5276c7a0a7443656dbf2be2a898f04 (patch)
tree394abf5b590046f4a5d4053d633ceeb9e2a8520b
parent7fb0dc955a99f0f9f82bbf69aeaf3b327717925b (diff)
downloadtxr-f7418016db5276c7a0a7443656dbf2be2a898f04.tar.gz
txr-f7418016db5276c7a0a7443656dbf2be2a898f04.tar.bz2
txr-f7418016db5276c7a0a7443656dbf2be2a898f04.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;
}