From 5b71846a6561d20a0c954095f92cf125674ea8f1 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 14 Jul 2017 06:20:48 -0700 Subject: 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. --- eval.c | 10 ++++++++-- 1 file 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; } -- cgit v1.2.3