///|
pub fn render_function_instructions_diff_json(
report : FunctionInstructionsComparison,
) -> String {
let root : Map[String, Json] = Map([])
root.set("format", Json::string("moonsize-function-instructions-diff"))
root.set("schema_version", int_json(1))
root.set("baseline", function_instructions_json_value(report.baseline))
root.set("current", function_instructions_json_value(report.current))
root.set("scope", Json::string(report.scope))
let d = report.delta
let delta : Map[String, Json] = Map([])
delta.set("entry_bytes", int_json(d.entry_bytes))
delta.set("prefix_bytes", int_json(d.prefix_bytes))
delta.set("body_bytes", int_json(d.body_bytes))
delta.set("locals_bytes", int_json(d.locals_bytes))
delta.set("instruction_bytes", int_json(d.instruction_bytes))
delta.set("instruction_count", int_json(d.instruction_count))
root.set("delta", Json::object(delta))
root.set(
"opcodes",
Json::array(
report.opcodes.map(fn(row) {
let item : Map[String, Json] = Map([])
item.set("mnemonic", Json::string(row.mnemonic))
item.set("baseline_count", int_json(row.baseline_count))
item.set("current_count", int_json(row.current_count))
item.set("count_delta", int_json(row.count_delta))
item.set("baseline_encoded_bytes", int_json(row.baseline_encoded_bytes))
item.set("current_encoded_bytes", int_json(row.current_encoded_bytes))
item.set("encoded_bytes_delta", int_json(row.encoded_bytes_delta))
Json::object(item)
}),
),
)
Json::object(root).stringify(indent=2) + "\n"
}
///|
pub fn render_function_instructions_diff(
report : FunctionInstructionsComparison,
top : Int,
) -> String {
let out = StringBuilder()
out.write_string("FUNCTION INSTRUCTION COMPOSITION COMPARISON\n\n")
out.write_string(
"Explicit user-selected targets; no automatic function matching.\n",
)
for
(side, target) in [
("Baseline", report.baseline),
("Current", report.current),
] {
out.write_string(
"\n\{side}: \{target.file_size} B; SHA-256 \{target.sha256}; function \{target.index}\n",
)
out.write_string(
" name: " +
search_terminal_string(target.name) +
"; raw_name: " +
path_optional_string(target.raw_name).stringify() +
"\n",
)
for
(label, range) in [
("entry", target.entry),
("body", target.body),
("prefix", target.prefix),
("locals", target.locals_encoding),
] {
out.write_string(
" \{label}: file offset \{range.file_offset}, size \{range.size} B\n",
)
}
out.write_string(
" Encoded bytes: \{target.entry.size} B = prefix \{target.prefix.size} B + body \{target.body.size} B\n",
)
out.write_string(
" Body bytes: \{target.body.size} B = locals \{target.locals_encoding.size} B + instructions \{target.instruction_bytes} B; count \{target.instruction_count}\n",
)
}
let b = report.baseline
let c = report.current
let d = report.delta
out.write_string(
"\nBYTE AND COUNT LEDGER (delta = current - baseline)\nMETRIC BASELINE CURRENT DELTA\n",
)
for
(label, before, after, change) in [
("Entry bytes", b.entry.size, c.entry.size, d.entry_bytes),
("Prefix bytes", b.prefix.size, c.prefix.size, d.prefix_bytes),
("Body bytes", b.body.size, c.body.size, d.body_bytes),
(
"Locals bytes",
b.locals_encoding.size,
c.locals_encoding.size,
d.locals_bytes,
),
(
"Instruction bytes",
b.instruction_bytes,
c.instruction_bytes,
d.instruction_bytes,
),
(
"Instruction count",
b.instruction_count,
c.instruction_count,
d.instruction_count,
),
] {
out.write_string("\{label} \{before} \{after} \{change}\n")
}
out.write_string(
"Entry delta: \{d.entry_bytes} B = prefix \{d.prefix_bytes} B + body \{d.body_bytes} B\n",
)
out.write_string(
"Body delta: \{d.body_bytes} B = locals \{d.locals_bytes} B + instructions \{d.instruction_bytes} B\n",
)
let shown = top.max(0).min(report.opcodes.length())
out.write_string(
"\nOPCODE COMPOSITION: showing \{shown} of \{report.opcodes.length()} (absolute byte delta descending, absolute count delta descending, mnemonic ascending)\nMNEMONIC BEFORE COUNT AFTER COUNT COUNT DELTA BEFORE B AFTER B BYTE DELTA\n",
)
for i in 0..