diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-04-28 20:41:22 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-04-28 20:41:22 -0700 |
commit | 48ffaab4f43b4f6a2d550f08722dd9558adbf5e1 (patch) | |
tree | 4197dcbfea55b397d72fb70669c0c0c17fea5d4c /eval.c | |
parent | 44aa252186ff37ab871c5b66e62ad26abeb5b385 (diff) | |
download | txr-48ffaab4f43b4f6a2d550f08722dd9558adbf5e1.tar.gz txr-48ffaab4f43b4f6a2d550f08722dd9558adbf5e1.tar.bz2 txr-48ffaab4f43b4f6a2d550f08722dd9558adbf5e1.zip |
macros: lexical-var-p: don't report t for specials.
The lexical-var-p function wrongly reports true for locally
rebound special variables, which are not lexical.
* eval.c (special_var_p): Static function moved to avoid
forward declaration.
(lexical_var_p): Bail if sym satisfies special_var_p.
(old_lexical_var_p): New function, copy of old lexical_var_p
before this bugfix.
(eval_init): Conditionally register lexical-var-p as either
lexical_var_p or old_lexical_var_p depending on the compat
value.
* txr.1: Update documentation for lexical-var-p to clarify
that it doesn't report true for specials. Also make note that
it doesn't report true for global lexicals, and likewise that
lexical-fun-p doesn't report global functions.
Added compat note.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 38 |
1 files changed, 30 insertions, 8 deletions
@@ -715,10 +715,19 @@ static val reparent_env(val child, val parent) return child; } +static val special_var_p(val sym) +{ + uses_or2; + return or2(gethash(special, sym), + if2(lisplib_try_load(sym), gethash(special, sym))); +} + static val lexical_var_p(val menv, val sym) { if (nilp(menv)) { return nil; + } else if (special_var_p(sym)) { + return nil; } else { type_check(lit("lexical-var-p"), menv, ENV); @@ -732,6 +741,23 @@ static val lexical_var_p(val menv, val sym) } } +static val old_lexical_var_p(val menv, val sym) +{ + if (nilp(menv)) { + return nil; + } else { + type_check(lit("lexical-var-p"), menv, ENV); + + { + val binding = assoc(sym, menv->e.vbindings); + + if (binding) + return tnil(cdr(binding) == special_s); + return lexical_var_p(menv->e.up_env, sym); + } + } +} + static val lexical_fun_p(val menv, val sym) { if (nilp(menv)) { @@ -780,13 +806,6 @@ static val mark_special(val sym) return sethash(special, sym, t); } -static val special_var_p(val sym) -{ - uses_or2; - return or2(gethash(special, sym), - if2(lisplib_try_load(sym), gethash(special, sym))); -} - static void copy_env_handler(mem_t *ptr) { val *penv = coerce(val *, ptr); @@ -6793,7 +6812,10 @@ void eval_init(void) reg_fun(intern(lit("env-vbindings"), user_package), func_n1(env_vbindings)); reg_fun(intern(lit("env-fbindings"), user_package), func_n1(env_fbindings)); reg_fun(intern(lit("env-next"), user_package), func_n1(env_next)); - reg_fun(intern(lit("lexical-var-p"), user_package), func_n2(lexical_var_p)); + reg_fun(intern(lit("lexical-var-p"), user_package), + func_n2(if3(opt_compat && opt_compat <= 257, + old_lexical_var_p, + lexical_var_p))); reg_fun(intern(lit("lexical-fun-p"), user_package), func_n2(lexical_fun_p)); reg_fun(intern(lit("lexical-lisp1-binding"), user_package), func_n2(lexical_lisp1_binding)); |