summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-06 00:14:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-06 00:14:34 -0700
commitce6a804af6cc225f0078cf2244c12aa374e63c8b (patch)
tree4f0052f0420c3deb28739f850b2db850f4bccaaf /share
parentd453e38a773a618ead6772f34c9beff73b0c2d1d (diff)
downloadtxr-ce6a804af6cc225f0078cf2244c12aa374e63c8b.tar.gz
txr-ce6a804af6cc225f0078cf2244c12aa374e63c8b.tar.bz2
txr-ce6a804af6cc225f0078cf2244c12aa374e63c8b.zip
each: fix (each ()) segfault.
The (each ()) form should infinitely loop, and the compiled version does. The interpreter crashes, when that is a top-level form. The reason is that the underlying sys:each-op operator uses an empty list of variable names as an indication to use the bindings from the parent lexical environment. And in that particular case, the let is also empty. The whole thing looks like: (let () (sys:each-op each nil)) If this is a top-level expression, then op_let receives a null environment pointer. Since it has no bindings to add, it doesn't extend the environment chain and passes a null environment pointer down to op_each, which that tries to use, because it's told to reach into it for bindings. Let's use the t symbol for that instead, so then the above would look like: ;; the t and only the t means "access parent env" (let () (sys:each-op each t)) And then, let's also fix it so that t is never used in this case when there are no vars: ;; no t, and so don't access parent env. (let () (sys:each-op each nil)) * eval.c (op_each): Get the bindings from the parent environment if vars is t, rather than when it's null. (me_each): When the symbols are not being inserted into the sys:each-op form, then insert t to indicate that, rather than nil. If the source form specifies an empty list of bindings, then insert nil, not t. * share/txr/stdlib/compiler.tl (expand-each): Get the list of variable names from the parent lexical environment when vars is t, rather than when it's null.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/compiler.tl2
1 files changed, 1 insertions, 1 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 36e33007..f245e9f5 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -1379,7 +1379,7 @@
(defun expand-each (form env)
(mac-param-bind form (op each-type vars . body) form
- (unless vars
+ (when (eq vars t)
(set vars [mapcar car env.vb]))
(let* ((gens (mapcar (ret (gensym)) vars))
(out (if (member each-type '(collect-each append-each))