Skip to main content

Module render

Module render 

Source
Expand description

The VM’s normalized differential render — format-locked to sui_eval::render::render_tree, and refusing (never placeholdering) an unforced thunk. The VM’s normalized differential render — the third member of a format-locked family.

§Why this is not to_string_keyed + string_keyed_to_json

Two renders for a VM value already existed and neither can be used for a differential:

  • VMValue::to_string_keyed maps an unforced thunk to StringKeyedValue::Lambda. A value the VM failed to force therefore renders exactly like a value that legitimately is a function — and on the other side of the comparison the tree-walker’s real lambda renders <<lambda>> too. The two compare equal, so a fixture the VM could not evaluate reports agreement.
  • string_keyed_to_json (private, in the sui binary at src/main.rs) renders a thunk as the literal string "<thunk>" and has neither CppNix’s outPath/__toString rule nor any forcing. It disagrees with the walker’s Value::to_json on both counts. It is not lifted here — see the divergence note below.

§What this does instead

[render_vm] emits the byte-identical form of [sui_eval::render::render_tree] — CppNix float format, attrs sorted by resolved name, the walker’s string escaping, raw (unquoted) paths, and the same 128-deep <...> cap — with one deliberate difference:

A residual thunk is an Err, never a placeholder.

VM::execute already deep-forces its result, so a Thunk still standing at render time means forcing genuinely did not happen. Rendering that as <<lambda>> (what to_string_keyed does) or as "<thunk>" (what the binary’s helper does) would let it compare equal to the other engine’s placeholder. Refusing is the only rendering that cannot launder a non-answer into an agreement.

§The residual placeholder, stated rather than hidden

<<lambda>> and <<builtin n>> are still emitted for values that really are functions, exactly as render_tree does for the walker. Two engines that both produce a function agree on the render without agreeing on the body. That is a property of the walker’s own differential render, not something introduced here, and it is why lang_corpus_vm.rs additionally pins that no agreeing corpus row contains a placeholder at all.

§Divergence recorded, not papered over

The binary’s string_keyed_to_json and the walker’s Value::to_json disagree: the walker implements CppNix’s rule that an attrset carrying outPath / __toString serializes as that string, and it forces thunks; the binary’s helper does neither. This module sides with neither — it is not a JSON renderer at all, it is the walker’s differential render, which is a third form that predates both and is the one already used to compare two engines (sui-ir/tests/common/render.rs). The outPath rule is therefore out of scope here and still unreconciled between those two JSON paths; nothing in this file makes that better or worse.

Constants§

DEEP_SENTINEL
The identical marker every engine emits past MAX_RENDER_DEPTH.
MAX_RENDER_DEPTH
Render-recursion depth cap — must equal sui_eval::render::MAX_RENDER_DEPTH and sui_ir::render::MAX_RENDER_DEPTH.

Functions§

escape_str
The walker’s Display string escaping — must equal sui_eval::render::escape_str.
render_vm
Render a VMValue to the normalized differential form.