summaryrefslogtreecommitdiffstats
path: root/parser.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-11-23 20:47:41 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-11-23 20:47:41 -0800
commitdbbe05f214787b6ef8f90bda8ea3458a72e3081b (patch)
tree171010986d8babebc4493661c62f6a652620df65 /parser.c
parent026acf026747478ed25f20671b43c084dd0cbff8 (diff)
downloadtxr-dbbe05f214787b6ef8f90bda8ea3458a72e3081b.tar.gz
txr-dbbe05f214787b6ef8f90bda8ea3458a72e3081b.tar.bz2
txr-dbbe05f214787b6ef8f90bda8ea3458a72e3081b.zip
bugfix: reading hash literals with circ notation.
The backpatching of literal hash objects containing circular notation labels is incorrect, because it directly mutates the hash keys, without regard for the fact that this alters their hash values. This change makes the test case #1=#H(() (#1# #1#)) work properly: a hash which contains itself as a key and corresponding value. When this object is constructed by the reader, we can do a gethash call on it, using itself as the key, and it emerges as the value. Before this fix, nil would be returned indicating that the key is not found, although it is listed in the table (corrupt hash). * parser.c (circ_backpatch): When traversing a hash, local list of the cells. Then clear the hash, iterate the list of old cells, and re-insert the key-value pairs.
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/parser.c b/parser.c
index f3aed6e0..681ffe75 100644
--- a/parser.c
+++ b/parser.c
@@ -315,8 +315,19 @@ tail:
if (p->circ_count) {
val iter = hash_begin(obj);
val cell;
- while ((cell = hash_next(iter)))
+ val pairs = nil;
+
+ while ((cell = hash_next(iter))) {
circ_backpatch(p, &cs, cell);
+ push(cell, &pairs);
+ }
+
+ clearhash(obj);
+
+ while (pairs) {
+ val cell = pop(&pairs);
+ sethash(obj, car(cell), cdr(cell));
+ }
}
} else if (structp(obj)) {
val stype = struct_type(obj);