diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-11-04 06:44:25 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-11-04 06:44:25 -0800 |
commit | 8cdf0417090b2c6e6b29aa67c7b1efca5501bb7c (patch) | |
tree | 5d9420167dacb3314a3553b5c117d00b3664c52d | |
parent | 7ab744e142b33e641a72b163a4f6f9a2eaf18f15 (diff) | |
download | txr-8cdf0417090b2c6e6b29aa67c7b1efca5501bb7c.tar.gz txr-8cdf0417090b2c6e6b29aa67c7b1efca5501bb7c.tar.bz2 txr-8cdf0417090b2c6e6b29aa67c7b1efca5501bb7c.zip |
Pattern vars accessed from Lisp now dynamic.
* eval.c (set_dyn_env): Static function becomes external.
* eval.h (set_dyn_env): Declared.
* match.c (eval_with_bindings, eval_progn_with_bindings):
Evaluate Lisp code in null lexical environment. Instead
install the pattern variables as dynamic, so they shadow
global variables. A compatibility check for 121 or earlier
provides the old behavior.
* txr.1: Document scoping rules, and added compatibility
notes.
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | eval.h | 1 | ||||
-rw-r--r-- | match.c | 33 | ||||
-rw-r--r-- | txr.1 | 42 |
4 files changed, 73 insertions, 5 deletions
@@ -926,7 +926,7 @@ static void do_eval_args(val form, val env, val ctx_form, } } -static val set_dyn_env(val de) +val set_dyn_env(val de) { val old = dyn_env; dyn_env = de; @@ -38,6 +38,7 @@ val lookup_global_var(val sym); loc lookup_var_l(val env, val sym); loc lookup_global_var_l(val sym); val lookup_fun(val env, val sym); +val set_dyn_env(val de); val interp_fun(val env, val fun, struct args *); val boundp(val sym); val fboundp(val sym); @@ -283,20 +283,45 @@ static val eval_with_bindings(val form, val spec, val bindings, val ctx_form) { val ret; + uw_env_begin; - uw_set_match_context(cons(spec, bindings)); - ret = eval(form, make_env(bindings, nil, nil), ctx_form); + + if (opt_compat && opt_compat <= 121) { + uw_set_match_context(cons(spec, bindings)); + ret = eval(form, make_env(bindings, nil, nil), ctx_form); + } else { + val saved_de = set_dyn_env(make_env(bindings, nil, nil)); + + uw_set_match_context(cons(spec, bindings)); + ret = eval(form, nil, ctx_form); + + set_dyn_env(saved_de); + } + uw_env_end; return ret; } + static val eval_progn_with_bindings(val forms, val spec, val bindings, val ctx_form) { val ret; + uw_env_begin; - uw_set_match_context(cons(spec, bindings)); - ret = eval_progn(forms, make_env(bindings, nil, nil), ctx_form); + + if (opt_compat && opt_compat <= 121) { + uw_set_match_context(cons(spec, bindings)); + ret = eval_progn(forms, make_env(bindings, nil, nil), ctx_form); + } else { + val saved_de = set_dyn_env(make_env(bindings, nil, nil)); + + uw_set_match_context(cons(spec, bindings)); + ret = eval_progn(forms, nil, ctx_form); + + set_dyn_env(saved_de); + } + uw_env_end; return ret; } @@ -10442,6 +10442,34 @@ is provided by and .codn lexical-lisp1-binding . +.NP* Pattern Language and Lisp Scope Nesting + +\*(TL expressions can be embedded in the \*(TX pattern language in various +ways. Likewise, the pattern language can be invoked from \*(TL. This +creates the possibility that Lisp code makes references to variables +bound in the pattern language. The pattern language can also reference +Lisp variables indirectly using the +.code @ +escape to evaluate a variable reference as Lisp code. Plain variable +references in the pattern language do not refer to Lisp variables. + +The rules are as follows, but they haven't always been that way. +See the COMPATIBILITY section. + +A Lisp expression evaluated from the \*(TX pattern language executes +in a null lexical environment. The current set of pattern variables captured +up to that point by the pattern language are installed as dynamic variables. +They shadow any Lisp global variables (whether those are defined +by +.code defvar +or +.codn defvarl ). + +The variable bindings are also stored in a dynamic environment frame. +When \*(TX pattern code is re-entered from Lisp, these bindings are picked +up from the closest environment frame, allowing the pattern code to +continue with those bindings. + .SH* LISP OPERATOR, FUNCTION AND MACRO REFERENCE .SS* Conventions @@ -37246,6 +37274,20 @@ is given an argument which is equal or lower. For instance .code -C 103 selects the behaviors described below for version 105, but not those for 102. +.IP 121 +In \*(TX 121 and earlier versions, \*(TL expressions evaluated in the +pattern language were placed in a lexical environment in which the +pattern variables were visible as lexical variables. The meant that +these variables could be directly captured in lexical closures. On the other +hand, it meant that a Lisp function defined in a +.code @(do) +block could not access a variable established by a later +.codn @(bind) . +It doesn't make sense for dynamically captured variables to be lexical, +so the rule was changed. The backward compatibility switch will enable +the old scoping behavior. Capturing the values of pattern variables in +closures is possible indirectly under the new rule: simply bind new lexical +variables with their values. .IP 118 The .code slot-p |