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
@@ -141,6 +141,34 @@ static const char* coreLibSource =
"}\n"
"\n"
"class String is Sequence {\n"
" // Avoids recursively calling [toString] on [object] and overflowing the\n"
" // stack.\n"
" //\n"
" // If we are already within a call to [safeToString_] on [object] in this\n"
" // fiber, then this returns \"...\". Otherwise, it returns the result of\n"
" // calling [ifUnseen].\n"
" static safeToString_(object, ifUnseen) {\n"
" if (__seenByFiber == null) __seenByFiber = new Map\n"
" var seen = __seenByFiber[Fiber.current]\n"
" if (seen == null) {\n"
" __seenByFiber[Fiber.current] = seen = new List\n"
" }\n"
"\n"
" // See if we are recursing on it.\n"
" for (outer in seen) {\n"
" if (Object.same(outer, object)) return \"...\"\n"
" }\n"
"\n"
" seen.add(object)\n"
"\n"
" var result = ifUnseen.call()\n"
"\n"
" seen.removeAt(-1)\n"
" if (seen.count == 0) __seenByFiber.remove(Fiber.current)\n"
"\n"
" return result\n"
" }\n"
"\n"
" bytes { new StringByteSequence(this) }\n"
"}\n"
"\n"
@@ -162,7 +190,7 @@ static const char* coreLibSource =
" return other\n"
" }\n"
"\n"
" toString { \"[\" + join(\", \") + \"]\" }\n"
" toString { String.safeToString_(this) { \"[\" + join(\", \") + \"]\" } }\n"
"\n"
" +(other) {\n"
" var result = this[0..-1]\n"
@@ -178,16 +206,18 @@ static const char* coreLibSource =
" values { new MapValueSequence(this) }\n"
"\n"
" toString {\n"
" var first = true\n"
" var result = \"{\"\n"
" return String.safeToString_(this) {\n"
" var first = true\n"
" var result = \"{\"\n"
"\n"
" for (key in keys) {\n"
" if (!first) result = result + \", \"\n"
" first = false\n"
" result = result + key.toString + \": \" + this[key].toString\n"
" for (key in keys) {\n"
" if (!first) result = result + \", \"\n"
" first = false\n"
" result = result + key.toString + \": \" + this[key].toString\n"
" }\n"
"\n"
" return result + \"}\"\n"
" }\n"
"\n"
" return result + \"}\"\n"
" }\n"
"}\n"
"\n"