ValueRender

internal object ValueRender

The => type = value line, for both the single-tick result and every cross-tick McpScope.yield — one function, so the two cannot drift apart.

toString() is the fallback and is right for almost everything. It is replaced only where the JVM representation is an address or a lie (an unsigned array prints its signed storage). Value classes are reachable by is here only when they arrive boxed, which yield's reified parameter guarantees; a single-tick value-class RESULT does not, since it is read back off an unboxed backing field.

A type keeps its own toString() unless it holds something opaque, and only a walk can tell — so every container is walked, and the walk stands when it changed something. Where toString() is a stock one (SELF_RENDERING) it stands when it changed nothing too: unchanged, it IS that string, which toString() would only print again. Only a type with a format of its own pays for a second pass. A container reached from inside itself renders as CYCLE, and that counts as a change — so a cyclic value never falls back to the toString() that would follow the cycle forever.

Everything appends into ONE builder and answers with a Boolean, so the payload is materialized exactly once. A String per node costs one copy per level of nesting plus one for the head — at depth 1, the whole payload.

Types

Link copied to clipboard
private class Sink(val sb: StringBuilder)

One line call's state: the buffer and the ancestors on the way down — one lifetime, so they travel as fields rather than through every signature.

Properties

Link copied to clipboard
private const val CYCLE: String

A container reached from inside itself; the spelling Arrays.deepToString uses for the same thing.

Link copied to clipboard
private const val MAX_NESTING: Int = 64

A hard stop on nesting. This walk spends several frames per level — where the contentDeepToString it replaced spent one — and it runs on the game thread, so depth has to be bounded somewhere. The chain is the ancestor list, so its size IS the depth; no counter to thread through.

Link copied to clipboard

Whether a class's toString() prints exactly what an unchanged walk of it printed, so the walk can stand in for it: the JDK's stock printers — AbstractCollection's [a, b], AbstractMap's {k=v}, the formats Sink.walk and Sink.walkMap copy (their (this ...) never meets an unchanged walk: a self-reference is a CYCLE) — and Pair/Triple, final, whose (a, b) is the tuple walk's own.

Link copied to clipboard
private const val TOO_DEEP: String

Nesting past MAX_NESTING: there is more here, it just isn't worth the stack. Angle-bracketed like <lambda> and threw — this file's mark for the renderer speaking rather than showing a value.

Functions

Link copied to clipboard
private fun ambiguousBare(v: String): Boolean

Whether v read bare would say something it is not — nothing at all, or a null. Not every string: quoting costs two characters per element inside a container. Edges tested directly, not through trim(), which copies the whole string exactly when the check matches. isEmpty first, or v[0] throws.

Link copied to clipboard
fun line(type: String, value: Any?): StringBuilder

The builder, not a String: the head is already in it when the payload lands, so it costs no copy of its own. Both callers consume it at once — one toString(), one append.

Link copied to clipboard
private fun overridesToString(v: Any): Boolean

Whether v's class says anything of its own, or inherits Object's Type@hexHash. Any::class.java IS java.lang.Object.class — the comparison is against the real declaring class, not a Kotlin alias.

Link copied to clipboard
private fun threw(v: Any, t: Throwable): String

toString() is caller code and may throw; a value that cannot render must not fail the eval that made it. Per ELEMENT so one bad entry costs its slot, not the line — Sink.render backstops what walking can't reach.