Don't stackoverflow on recursive lists and maps. Fix #3.

This commit is contained in:
Bob Nystrom
2015-05-03 11:13:05 -07:00
parent 3f06553f7f
commit 40897f3348
4 changed files with 137 additions and 20 deletions
+39 -9
View File
@@ -127,6 +127,34 @@ class WhereSequence is Sequence {
}
class String is Sequence {
// Avoids recursively calling [toString] on [object] and overflowing the
// stack.
//
// If we are already within a call to [safeToString_] on [object] in this
// fiber, then this returns "...". Otherwise, it returns the result of
// calling [ifUnseen].
static safeToString_(object, ifUnseen) {
if (__seenByFiber == null) __seenByFiber = new Map
var seen = __seenByFiber[Fiber.current]
if (seen == null) {
__seenByFiber[Fiber.current] = seen = new List
}
// See if we are recursing on it.
for (outer in seen) {
if (Object.same(outer, object)) return "..."
}
seen.add(object)
var result = ifUnseen.call()
seen.removeAt(-1)
if (seen.count == 0) __seenByFiber.remove(Fiber.current)
return result
}
bytes { new StringByteSequence(this) }
}
@@ -148,7 +176,7 @@ class List is Sequence {
return other
}
toString { "[" + join(", ") + "]" }
toString { String.safeToString_(this) { "[" + join(", ") + "]" } }
+(other) {
var result = this[0..-1]
@@ -164,16 +192,18 @@ class Map {
values { new MapValueSequence(this) }
toString {
var first = true
var result = "{"
return String.safeToString_(this) {
var first = true
var result = "{"
for (key in keys) {
if (!first) result = result + ", "
first = false
result = result + key.toString + ": " + this[key].toString
for (key in keys) {
if (!first) result = result + ", "
first = false
result = result + key.toString + ": " + this[key].toString
}
return result + "}"
}
return result + "}"
}
}