summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib.c35
-rw-r--r--stream.h1
-rw-r--r--tests/012/circ.expected2
-rw-r--r--tests/012/circ.tl14
4 files changed, 40 insertions, 12 deletions
diff --git a/lib.c b/lib.c
index 7b67c4d1..b45547b3 100644
--- a/lib.c
+++ b/lib.c
@@ -9521,12 +9521,23 @@ static void populate_obj_hash(val obj, struct strm_ctx *ctx)
{
tail:
if (circle_print_eligible(obj)) {
- val new_p;
- val cell = gethash_c(ctx->obj_hash, obj, mkcloc(new_p));
+ if (ctx->obj_hash_prev) {
+ val prev_cell;
+ val label = gethash_f(ctx->obj_hash_prev, obj, mkcloc(prev_cell));
+
+ if (label == colon_k)
+ uw_throwf(error_s, lit("print: unexpected duplicate object "
+ "(misbehaving print method?)"), nao);
+ if (prev_cell)
+ return;
+ } else {
+ val new_p;
+ val cell = gethash_c(ctx->obj_hash, obj, mkcloc(new_p));
- if (!new_p) {
- rplacd(cell, t);
- return;
+ if (!new_p) {
+ rplacd(cell, t);
+ return;
+ }
}
} else {
return;
@@ -9592,11 +9603,9 @@ static void obj_hash_merge(val parent_hash, val child_hash)
val pcell = gethash_c(parent_hash, car(cell), mkcloc(new_p));
if (new_p)
rplacd(pcell, cdr(cell));
- else if (cdr(pcell) == colon_k)
+ else
uw_throwf(error_s, lit("print: unexpected duplicate object "
- "(misbehaving print method?)"), nao);
- else if (!cdr(pcell))
- rplacd(pcell, t);
+ "(internal error?)"), nao);
}
}
@@ -9615,15 +9624,17 @@ val obj_print(val obj, val out, val pretty)
uw_simple_catch_begin;
if (ctx) {
- val prev_hash = ctx->obj_hash;
+ ctx->obj_hash_prev = ctx->obj_hash;
ctx->obj_hash = make_hash(nil, nil, nil);
populate_obj_hash(obj, ctx);
- obj_hash_merge(prev_hash, ctx->obj_hash);
- ctx->obj_hash = prev_hash;
+ obj_hash_merge(ctx->obj_hash_prev, ctx->obj_hash);
+ ctx->obj_hash = ctx->obj_hash_prev;
+ ctx->obj_hash_prev = nil;
} else {
if (cdr(lookup_var(nil, print_circle_s))) {
ctx = &ctx_struct;
ctx->obj_hash = make_hash(nil, nil, nil);
+ ctx->obj_hash_prev = nil;
ctx->counter = zero;
get_set_ctx(out, ctx);
populate_obj_hash(obj, ctx);
diff --git a/stream.h b/stream.h
index 818ad9cd..0cc7810a 100644
--- a/stream.h
+++ b/stream.h
@@ -39,6 +39,7 @@ enum indent_mode {
struct strm_ctx {
val obj_hash;
+ val obj_hash_prev;
val counter;
};
diff --git a/tests/012/circ.expected b/tests/012/circ.expected
new file mode 100644
index 00000000..4927381e
--- /dev/null
+++ b/tests/012/circ.expected
@@ -0,0 +1,2 @@
+[["a"]]
+(#1=("a") [[#1#]])
diff --git a/tests/012/circ.tl b/tests/012/circ.tl
new file mode 100644
index 00000000..4b6e9990
--- /dev/null
+++ b/tests/012/circ.tl
@@ -0,0 +1,14 @@
+(defstruct circ-print nil
+ a
+ (:method print (me stream pretty-p)
+ (put-string "[[" stream)
+ (print me.a stream pretty-p)
+ (put-string "]]" stream)))
+
+(defvar x (let* ((l (list "a"))
+ (c (new circ-print a l)))
+ (list l c)))
+
+(let ((*print-circle* t))
+ (prinl (new circ-print a "a"))
+ (prinl x))