src/mimir_lens/room_feed/fixture/groups.rs
//! The fixture of `group_twins` on the compiled graph: one repo `grp`
//! (crate grp@0.1.0) whose dump carries what the driver writes BELOW a
//! function — CALLS and READS_FIELD edges with one site per line, and `local`
//! parts with their inferred types and lines.
//!
//! ```text
//! src/lib.rs
//! Ledger { entries, seed }
//! summarise ─┐ ONE compiled group: the same resolved callees, fields and let
//! rollup ─┘ types, line for line. rollup's copy is written in call
//! syntax the other way round (`Ledger::weigh(book, item)` vs
//! `ledger.weigh(e)`, `u64::wrapping_mul(roll, …)` vs
//! `carry.wrapping_mul(…)`), its locals are renamed, and two
//! unrelated statements are INTERLEAVED into it — the source
//! text normalises to different bodies; the graph sees one group
//! bg0..bg29 the common case: one let, one own callee, `Vec::push`
//! ```
//!
//! The checkout is written at `<tmp>/git/grp`, where the source lenses look
//! for it. The warehouse holds NO embeddings table.
use std::collections::BTreeSet;
use std::path::PathBuf;
use mimir_ingest::CommitDump;
use mimir_schema::{EdgeKind, EdgeRow, Level, Origin, SpanRow, moniker};
use super::vectors::{Source, consume_next};
use super::{N, Workspace, e, n, site, span, unit};
use crate::code_room::CodeRoom;
use crate::warehouse::iceberg::IcebergWarehouse;
pub const GRP: &str = "grp";
pub fn grp(d: &str) -> String {
moniker::moniker("grp", "0.1.0", d)
}
/// A callee of the dependency `dep` (a reference stub).
fn dep(d: &str) -> String {
moniker::moniker("dep", "1.2.3", d)
}
/// One body line: its text and the compiled facts on it.
struct Line {
text: &'static str,
calls: Vec<String>,
fields: Vec<&'static str>,
/// `(name, type)` of a `let` on this line.
local: Option<(&'static str, &'static str)>,
}
fn line(text: &'static str, calls: &[String], fields: &[&'static str], local: Option<(&'static str, &'static str)>) -> Line {
Line { text, calls: calls.to_vec(), fields: fields.to_vec(), local }
}
fn open() -> String {
dep("impl#[Store]open().")
}
fn weigh() -> String {
dep("impl#[Store]weigh().")
}
fn sort_by_weight() -> String {
dep("impl#[Store]sort_by_weight().")
}
fn core(d: &str) -> String {
moniker::moniker("core", "1.0.0", d)
}
/// The planted group as `summarise` writes it.
fn summarise() -> Vec<Line> {
let (wm, push, len) = (core("impl#[u64]wrapping_mul()."), core("impl#[Vec]push()."), core("impl#[Vec]len()."));
vec![
line("pub fn summarise(ledger: &Ledger) -> u64 {", &[], &[], None),
line(" let mut acc: Vec<(String, u64)> = Vec::new();", &[], &[], Some(("acc", "Vec<(String, u64)>"))),
line(" let mut carry: u64 = 7;", &[], &[], Some(("carry", "u64"))),
line(" for e in ledger.open().entries.iter() {", &[open()], &["entries"], None),
line(" let w = ledger.weigh(e) + carry;", &[weigh()], &[], Some(("w", "u64"))),
line(" carry = carry.wrapping_mul(ledger.seed);", &[wm], &["seed"], None),
line(" acc.push((e.to_string(), w));", &[push], &[], None),
line(" }", &[], &[], None),
line(" ledger.sort_by_weight(&mut acc, &ledger.entries);", &[sort_by_weight()], &["entries"], None),
line(" acc.len() as u64", &[len], &[], None),
line("}", &[], &[], None),
]
}
/// The same group in `rollup`: other call syntax, renamed locals, two
/// unrelated statements interleaved (lines 4 and 7 of the item).
fn rollup() -> Vec<Line> {
let (wm, push, len) = (core("impl#[u64]wrapping_mul()."), core("impl#[Vec]push()."), core("impl#[Vec]len()."));
vec![
line("pub fn rollup(book: &Ledger, route: &str) -> u64 {", &[], &[], None),
line(" let mut bucket: Vec<(String, u64)> = Vec::new();", &[], &[], Some(("bucket", "Vec<(String, u64)>"))),
line(" let mut roll: u64 = 9;", &[], &[], Some(("roll", "u64"))),
line(" log_route(route);", &[dep("log_route().")], &[], None),
line(" for item in Store::open(book).entries.iter() {", &[open()], &["entries"], None),
line(" let weight = Store::weigh(book, item) + roll;", &[weigh()], &[], Some(("weight", "u64"))),
line(" let banner = route.to_ascii_uppercase();", &[core("impl#[str]to_ascii_uppercase().")], &[], Some(("banner", "String"))),
line(" roll = u64::wrapping_mul(roll, book.seed);", &[wm], &["seed"], None),
line(" Vec::push(&mut bucket, (item.to_string(), weight));", &[push], &[], None),
line(" }", &[], &[], None),
line(" Store::sort_by_weight(book, &mut bucket, &book.entries);", &[sort_by_weight()], &["entries"], None),
line(" Vec::len(&bucket) as u64", &[len], &[], None),
line("}", &[], &[], None),
]
}
/// The common case: `bg{i}` binds a `u64`, calls its own `step{i}`, pushes.
fn background(i: usize) -> (String, Vec<Line>) {
let text = |s: String| -> &'static str { Box::leak(s.into_boxed_str()) };
let name = format!("bg{i}");
let lines = vec![
line(text(format!("pub fn {name}(x: u64, out: &mut Vec<u64>) {{")), &[], &[], None),
line(" let y: u64 = x + 1;", &[], &[], Some(("y", "u64"))),
line(text(format!(" step{i}(y);")), &[dep(&format!("step{i}()."))], &[], None),
line(" out.push(y);", &[core("impl#[Vec]push().")], &[], None),
line("}", &[], &[], None),
];
(name, lines)
}
fn commit(root: &std::path::Path) -> CommitDump {
let krate = grp("crate/");
let strukt = grp("Ledger#");
let field = |f: &str| grp(&format!("Ledger#{f}."));
let mut fns: Vec<(String, Vec<Line>)> = vec![("summarise".into(), summarise()), ("rollup".into(), rollup())];
fns.extend((0..30).map(background));
let mut src = Source::default();
src.plain("//! grp\n\npub struct Ledger {\n pub entries: Vec<u64>,\n pub seed: u64,\n}\n");
for (name, lines) in &fns {
let text: Vec<&str> = lines.iter().map(|l| l.text).collect();
src.item(&grp(&format!("{name}().")), 0, &text.join("\n"));
}
let mut spans: Vec<SpanRow> = src.write(root, "src/lib.rs");
let starts: std::collections::BTreeMap<String, u32> = spans.iter().map(|s| (s.key.clone(), s.start_line)).collect();
let mut nodes: Vec<N> = vec![
n(krate.clone(), "crate", Level::Crate, "grp", None),
n(strukt.clone(), "struct", Level::Item, "Ledger", Some(krate.clone())),
n(field("entries"), "field", Level::Part, "entries", Some(strukt.clone())),
n(field("seed"), "field", Level::Part, "seed", Some(strukt.clone())),
];
let mut edges: Vec<EdgeRow> = vec![e(&krate, &strukt, EdgeKind::Contains, 1), e(&strukt, &field("entries"), EdgeKind::Contains, 1), e(&strukt, &field("seed"), EdgeKind::Contains, 1)];
let mut stubs: BTreeSet<String> = BTreeSet::new();
for (name, lines) in &fns {
let id = grp(&format!("{name}()."));
let start = starts[&id];
nodes.push(n(id.clone(), "fn", Level::Item, name, Some(krate.clone())));
edges.push(e(&krate, &id, EdgeKind::Contains, 1));
// one edge per (target, kind), one site per line it is on
let mut sites: std::collections::BTreeMap<(String, EdgeKind), Vec<u32>> = Default::default();
for (i, l) in lines.iter().enumerate() {
let at = start + i as u32;
for c in &l.calls {
stubs.insert(c.clone());
sites.entry((c.clone(), EdgeKind::Calls)).or_default().push(at);
}
for f in &l.fields {
sites.entry((field(f), EdgeKind::ReadsField)).or_default().push(at);
}
if let Some((local, ty)) = l.local {
let mut lid = id.clone();
moniker::push_descriptor(&mut lid, moniker::Suffix::Term, &format!("{local}@{at}"));
nodes.push(n(lid.clone(), "local", Level::Part, local, Some(id.clone())).ty(ty));
edges.push(e(&id, &lid, EdgeKind::Contains, 1));
spans.push(span(&lid, "src/lib.rs", at, at));
}
}
for ((to, kind), at) in sites {
edges.push(e(&id, &to, kind, at.len() as u32));
for l in at {
spans.push(site(&id, &to, kind, "src/lib.rs", l));
}
}
}
for s in &stubs {
let name = s.rsplit(['#', '/']).next().unwrap_or(s).trim_end_matches("().").to_string();
nodes.push(n(s.clone(), "fn", Level::Item, &name, None).stub(Origin::Library));
}
CommitDump {
toolchain: "nightly-fixture".into(),
workspace_crates: ["grp@0.1.0:lib".to_string()].into(),
workspace_targets: ["grp:lib".to_string()].into(),
failed_units: BTreeSet::new(),
owner_disambiguations: 0,
crates: vec![unit("grp@0.1.0:lib", nodes, edges, spans)],
binary: false,
binaries: vec![],
}
}
/// The workspace and its checkout.
pub struct Grp {
pub ws: Workspace,
root: PathBuf,
}
impl Grp {
/// `<tmp>/git/grp` — where the source lenses look.
pub fn checkout(&self) -> PathBuf {
self.root.join("git").join(GRP)
}
}
/// `grp` consumed at its first commit; no shape, no vector, no embeddings table.
pub fn build() -> Grp {
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path().to_path_buf();
let builds = root.join("builds");
std::fs::create_dir_all(&builds).unwrap();
let warehouse = IcebergWarehouse::open(&builds).unwrap();
let room = CodeRoom::new("groups", &builds);
let dir = root.join("git").join(GRP);
nornir_git::gitio::init(&dir).unwrap();
let dump = commit(&dir);
nornir_git::gitio::commit_all(&dir, "first").unwrap();
consume_next(&room, &dir, GRP, dump);
Grp { ws: Workspace { room, warehouse, builds, _tmp: tmp }, root }
}