///|
pub fn render_dependency_overlap(
report : DependencyOverlapReport,
top : Int,
) -> String {
let out = StringBuilder()
out.write_string(
"FUNCTION DEPENDENCY SET COMPARISON\n\nLeft #\{report.left_index}: " +
search_terminal_string(report.functions[report.left_index].name) +
"\nRight #\{report.right_index}: " +
search_terminal_string(report.functions[report.right_index].name) +
"\nInput: \{report.file_size} B; SHA-256 \{report.sha256}\n",
)
if !report.graph_warning.is_empty() {
out.write_string(report.graph_warning + "\n")
}
out.write_string("\nGROUP FUNCTIONS LOCAL IMPORTED LOCAL ENCODED BYTES\n")
for group in report.groups {
out.write_string(
"\{group.kind} \{group.function_count} \{group.local_count} \{group.imported_count} \{group.local_encoded_bytes}\n",
)
}
let s = report.groups[0]
let l = report.groups[1]
let r = report.groups[2]
let n = report.groups[3]
out.write_string(
"\nFunction ledger: all \{report.function_count} = shared \{s.function_count} + left_only \{l.function_count} + right_only \{r.function_count} + neither \{n.function_count}\nLeft functions: \{report.left_function_count} = left_only \{l.function_count} + shared \{s.function_count}\nRight functions: \{report.right_function_count} = right_only \{r.function_count} + shared \{s.function_count}\nUnion functions: \{report.union_function_count} = left_only \{l.function_count} + right_only \{r.function_count} + shared \{s.function_count}\nAll functions: \{report.function_count} = union \{report.union_function_count} + neither \{n.function_count}\nLocal encoded bytes: all \{report.local_encoded_bytes} = shared \{s.local_encoded_bytes} + left_only \{l.local_encoded_bytes} + right_only \{r.local_encoded_bytes} + neither \{n.local_encoded_bytes}\nLeft local bytes: \{report.left_local_encoded_bytes} = left_only \{l.local_encoded_bytes} + shared \{s.local_encoded_bytes}\nRight local bytes: \{report.right_local_encoded_bytes} = right_only \{r.local_encoded_bytes} + shared \{s.local_encoded_bytes}\nUnion local bytes: \{report.union_local_encoded_bytes} = left_only \{l.local_encoded_bytes} + right_only \{r.local_encoded_bytes} + shared \{s.local_encoded_bytes}\nAll local bytes: \{report.local_encoded_bytes} = union \{report.union_local_encoded_bytes} + neither \{n.local_encoded_bytes}\nComplete closure edges: left \{report.left_edges.length()}, right \{report.right_edges.length()} (not additive as unique call sites)\nUnresolved table call sites (no static candidates): \{report.unresolved_count}\n",
)
for i in 0..<3 {
let group = report.groups[i]
let order = group.indices.map(fn(index) { index })
order.sort_by(fn(a, b) {
let x = report.functions[a]
let y = report.functions[b]
if x.imported != y.imported {
return if x.imported { 1 } else { -1 }
}
let size = y.encoded_size.unwrap_or(0) - x.encoded_size.unwrap_or(0)
if size != 0 {
size
} else {
a - b
}
})
let shown = top.max(0).min(order.length())
out.write_string(
"\n\{group.kind}: showing \{shown} of \{group.function_count}\nINDEX IDENTITY ENCODED BYTES NAME\n",
)
for j in 0.. size.to_string()
None => "n/a (not measured)"
}
out.write_string(
"\{node.index} " +
(if node.imported { "imported" } else { "local" }) +
" " +
size +
" " +
search_terminal_string(node.name) +
"\n",
)
}
}
out.write_string(
"\nNeither members are summary-only here; complete indices are in JSON.\n" +
report.modeling_scope +
"\n",
)
out.to_string()
}
///|
pub fn render_dependency_overlap_json(
report : DependencyOverlapReport,
) -> String {
let root : Map[String, Json] = Map([])
root.set("format", Json::string("moonsize-dependency-overlap"))
root.set("schema_version", int_json(1))
root.set("file_size", int_json(report.file_size))
root.set("sha256", Json::string(report.sha256))
root.set("left_index", int_json(report.left_index))
root.set("right_index", int_json(report.right_index))
root.set("functions", Json::array(report.functions.map(path_node_json)))
root.set("left_reachable", Json::array(report.left_reachable.map(int_json)))
root.set("right_reachable", Json::array(report.right_reachable.map(int_json)))
root.set("left_edges", Json::array(report.left_edges.map(cycle_edge_json)))
root.set("right_edges", Json::array(report.right_edges.map(cycle_edge_json)))
root.set(
"groups",
Json::array(
report.groups.map(fn(group) {
let row : Map[String, Json] = Map([])
row.set("kind", Json::string(group.kind))
row.set("indices", Json::array(group.indices.map(int_json)))
row.set("function_count", int_json(group.function_count))
row.set("local_count", int_json(group.local_count))
row.set("imported_count", int_json(group.imported_count))
row.set("local_encoded_bytes", int_json(group.local_encoded_bytes))
Json::object(row)
}),
),
)
root.set("function_count", int_json(report.function_count))
root.set("local_function_count", int_json(report.local_function_count))
root.set("imported_function_count", int_json(report.imported_function_count))
root.set("local_encoded_bytes", int_json(report.local_encoded_bytes))
root.set("left_function_count", int_json(report.left_function_count))
root.set("left_local_count", int_json(report.left_local_count))
root.set("left_imported_count", int_json(report.left_imported_count))
root.set(
"left_local_encoded_bytes",
int_json(report.left_local_encoded_bytes),
)
root.set("right_function_count", int_json(report.right_function_count))
root.set("right_local_count", int_json(report.right_local_count))
root.set("right_imported_count", int_json(report.right_imported_count))
root.set(
"right_local_encoded_bytes",
int_json(report.right_local_encoded_bytes),
)
root.set("union_function_count", int_json(report.union_function_count))
root.set("union_local_count", int_json(report.union_local_count))
root.set("union_imported_count", int_json(report.union_imported_count))
root.set(
"union_local_encoded_bytes",
int_json(report.union_local_encoded_bytes),
)
root.set("graph_complete", Json::boolean(report.graph_complete))
root.set("unresolved_count", int_json(report.unresolved_count))
root.set("diagnostics", diagnostic_records_json(report.diagnostics))
root.set("graph_warning", Json::string(report.graph_warning))
root.set("modeling_scope", Json::string(report.modeling_scope))
Json::object(root).stringify(indent=2) + "\n"
}