diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-07-14 06:20:48 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-07-14 06:20:48 -0700 |
commit | 5b71846a6561d20a0c954095f92cf125674ea8f1 (patch) | |
tree | 394abf5b590046f4a5d4053d633ceeb9e2a8520b | |
parent | 974532041c1eaeb55c9fcb4c395e4da5f19a4773 (diff) | |
download | txr-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.c | 10 |
1 files changed, 8 insertions, 2 deletions
@@ -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; } |