From dbbe05f214787b6ef8f90bda8ea3458a72e3081b Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 23 Nov 2016 20:47:41 -0800 Subject: 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. --- parser.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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); -- cgit v1.2.3