diff --git a/scripts/circular.fe b/scripts/circular.fe new file mode 100644 index 0000000..1c0ef6e --- /dev/null +++ b/scripts/circular.fe @@ -0,0 +1,4 @@ +(= items (list 1 2 3 4)) +(setcar (cdr items) (cons items (cons 5 items))) +(setcdr (cdr (cdr (cdr items))) items) +(print items) diff --git a/src/fe.c b/src/fe.c index b4a1634..cd012ce 100644 --- a/src/fe.c +++ b/src/fe.c @@ -343,7 +343,7 @@ static void writestr(fe_Context *ctx, fe_WriteFn fn, void *udata, const char *s) while (*s) { fn(ctx, udata, *s++); } } -void fe_write(fe_Context *ctx, fe_Object *obj, fe_WriteFn fn, void *udata, int qt) { +static void write_(fe_Context *ctx, fe_Object *obj, fe_WriteFn fn, void *udata, int qt) { char buf[32]; switch (type(obj)) { @@ -357,22 +357,28 @@ void fe_write(fe_Context *ctx, fe_Object *obj, fe_WriteFn fn, void *udata, int q break; case FE_TPAIR: + if (tag(obj) & GCMARKBIT) { writestr(ctx, fn, udata, "..."); break; } fn(ctx, udata, '('); for (;;) { - fe_write(ctx, car(obj), fn, udata, 1); + /* mark 'obj' and write car(obj) */ + fe_Object *tmp = car(obj); + tag(obj) |= GCMARKBIT; + write_(ctx, tmp, fn, udata, 1); + /* write cdr(obj) if isn't circular list */ obj = cdr(obj); if (type(obj) != FE_TPAIR) { break; } fn(ctx, udata, ' '); + if (tag(obj) & GCMARKBIT) { writestr(ctx, fn, udata, "..."); break; } } - if (!isnil(obj)) { + if (!isnil(obj) && !(tag(obj) & GCMARKBIT)) { writestr(ctx, fn, udata, " . "); - fe_write(ctx, obj, fn, udata, 1); + write_(ctx, obj, fn, udata, 1); } fn(ctx, udata, ')'); break; case FE_TSYMBOL: - fe_write(ctx, car(cdr(obj)), fn, udata, 0); + write_(ctx, car(cdr(obj)), fn, udata, 0); break; case FE_TSTRING: @@ -395,6 +401,18 @@ void fe_write(fe_Context *ctx, fe_Object *obj, fe_WriteFn fn, void *udata, int q } } +static void unmarkpairs(fe_Object *obj) { + for (; !isnil(obj) && (tag(obj) & GCMARKBIT); obj = cdr(obj)) { + tag(obj) &= ~GCMARKBIT; + unmarkpairs(car(obj)); + } +} + +void fe_write(fe_Context *ctx, fe_Object *obj, fe_WriteFn fn, void *udata, int qt) { + write_(ctx, obj, fn, udata, qt); + unmarkpairs(obj); +} + static void writefp(fe_Context *ctx, void *udata, char chr) { unused(ctx);