src/mimir_lens/room_feed/fixture/clones.rs
//! The fixture of the clone signals: one repo `clo` (crate clo@0.1.0) whose
//! source is real text on disk and whose dump carries the edges signal 2
//! reads (params, the `->` part, USES_TYPE, READS_FIELD, CALLS).
//!
//! ```text
//! src/lib.rs
//! MapLayout { repos, plates }
//! tally ─┐ the SAME logic under unrelated names (a consistent rename,
//! summarize ─┘ another layout, other comments): exact + structural
//! tally_more tally with one statement changed: a near copy
//! place ─┐ unrelated names, DIFFERENT bodies, the same rare return
//! arrange ─┘ type and fields read: structural only
//! kill / delete name-alike, nothing alike in what they do: no signal
//! now_ms / now_unix_ms "milliseconds since the epoch" written twice (one-liners)
//! workspace_root / repo_root "where is the root", written twice, touching
//! other things: a Type-4 twin
//! sum_lanes_avx2 / sum_lanes_scalar one algorithm per CPU feature: deliberate
//! bump_alpha / bump_beta ONE body on two types (other params, other callees):
//! structure 0, but the same normalised body — a copy, never a twin
//! flag_a / flag_b two-feature accessors (`-> Option<bool>`, one field): too
//! little structure to be a structural or role pair
//! checksum a lone utility
//! step0..step29 the common case: `fn(&str) -> Result<(), Error>`
//! ```
//!
//! [`Clo::second_commit`]: `summarize` gets another body (seq 2).
//! [`Clo::commit_v`] `2`: … and `checksum` also calls `rotate_right` (its
//! features move); `3`: … and a new function `fold_bytes` (the population moves).
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use mimir_ingest::CommitDump;
use mimir_schema::{EdgeKind, EdgeRow, Level, moniker};
use super::vectors::{Source, callable, consume_next, stubs_into};
use super::{N, Workspace, e, n, unit};
use crate::code_room::CodeRoom;
use crate::warehouse::iceberg::IcebergWarehouse;
pub const CLO: &str = "clo";
pub fn clo(d: &str) -> String {
moniker::moniker("clo", "0.1.0", d)
}
pub const TALLY: &str = "/// Sum the plates above the floor, and count the repos.
pub fn tally(layout: &MapLayout, floor: u32) -> u32 {
let mut total = 0;
for plate in &layout.plates {
if *plate > floor {
total += *plate;
}
}
let mut seen = 0;
for repo in &layout.repos {
if !repo.is_empty() {
seen += 1;
}
}
total + seen
}";
/// TALLY consistently renamed, laid out and commented otherwise.
pub const SUMMARIZE: &str = "pub fn summarize(map: &MapLayout, min: u32) -> u32 {
// accumulate
let mut acc = 0;
for p in &map.plates { if *p > min { acc += *p; } }
let mut n = 0;
for r in &map.repos { if !r.is_empty() { n += 1; } }
acc + n
}";
const SUMMARIZE_2: &str = "pub fn summarize(map: &MapLayout, min: u32) -> u32 {
map.plates.iter().filter(|p| **p > min).sum::<u32>() + map.repos.len() as u32
}";
pub const TALLY_MORE: &str = "pub fn tally_more(layout: &MapLayout, floor: u32) -> u32 {
let mut total = 0;
for plate in &layout.plates {
if *plate > floor {
total += *plate;
}
}
let mut seen = 0;
for repo in &layout.repos {
if !repo.is_empty() {
seen += 1;
}
}
total + seen + 1
}";
const PLACE: &str = "pub fn place(seed: &MapLayout, extra: u32) -> MapLayout {
let mut repos = seed.repos.clone();
repos.sort();
MapLayout { repos, plates: seed.plates.iter().map(|p| p + extra).collect() }
}";
const ARRANGE: &str = "pub fn arrange(base: &MapLayout, names: &[String]) -> MapLayout {
let plates: Vec<u32> = base.plates.iter().rev().copied().collect();
let mut repos: Vec<String> = names.to_vec();
repos.extend(base.repos.iter().cloned());
MapLayout { repos, plates }
}";
pub const KILL: &str = "pub fn kill(pid: u32, table: &mut Vec<u32>) -> bool {
let before = table.len();
table.retain(|p| *p != pid);
before != table.len()
}";
pub const DELETE: &str = "pub fn delete(path: &str, cache: &mut String) -> usize {
let mut removed = 0;
while let Some(at) = cache.find(path) {
cache.replace_range(at..at + path.len(), \"\");
removed += 1;
}
removed
}";
/// "Seconds since the epoch", written twice (v1's nine-way twin): the same
/// role and meaning, another body.
pub const NOW_MS: &str = "pub fn now_ms() -> u64 {
SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_millis() as u64).unwrap_or(0)
}";
pub const NOW_UNIX_MS: &str = "pub fn now_unix_ms() -> u64 {
let now = SystemTime::now();
match now.duration_since(UNIX_EPOCH) {
Ok(elapsed) => elapsed.as_millis() as u64,
Err(_) => 0,
}
}";
/// "Where is the repository root", written twice (v1's seven-way twin): the
/// same idea, other calls — little structure in common.
pub const WORKSPACE_ROOT: &str = "pub fn workspace_root() -> PathBuf {
// the directory above this crate's manifest is the root
let here = PathBuf::from(env!(\"CARGO_MANIFEST_DIR\"));
let root = here.parent().map(Path::to_path_buf);
root.unwrap_or(here)
}";
pub const REPO_ROOT: &str = "pub fn repo_root() -> PathBuf {
// climb from here until the directory that holds the root
let mut here = std::env::current_dir().unwrap_or_default();
while !here.join(\".git\").exists() && here.pop() {}
here
}";
/// One algorithm written per CPU feature: the same body, deliberate.
fn sum_lanes(variant: &str) -> String {
let attr = if variant == "avx2" { "#[target_feature(enable = \"avx2\")]\n" } else { "" };
format!(
"{attr}pub unsafe fn sum_lanes_{variant}(xs: &[u32], floor: u32) -> u32 {{
let mut total = 0u32;
let mut i = 0;
while i + 8 <= xs.len() {{
for x in &xs[i..i + 8] {{
if *x > floor {{
total = total.wrapping_add(*x);
}}
}}
i += 8;
}}
for x in &xs[i..] {{
if *x > floor {{
total = total.wrapping_add(*x);
}}
}}
total
}}"
)
}
/// One body written on two types (`DatePicker::next_month` / `Calendar::next_month`
/// on the live forge): the same normalised text, other params and callees.
fn bump(ty: &str) -> String {
format!(
"pub fn bump_{ty}(xs: &mut Lanes, by: u32) -> u32 {{
let mut moved = 0;
for x in xs.iter_mut() {{
*x = x.wrapping_add(by);
moved += 1;
}}
xs.settle();
moved
}}"
)
}
/// A two-feature accessor.
fn flag(n: &str) -> String {
format!("pub fn flag_{n}() -> Option<bool> {{\n STATE.plates.first().map(|p| *p > 0)\n}}")
}
const CHECKSUM: &str = "pub fn checksum(bytes: &[u8]) -> u32 {
let mut acc = 17u32;
for b in bytes {
acc = acc.rotate_left(5) ^ u32::from(*b);
}
acc
}";
/// `checksum` at variant 2: one call more (`rotate_right`) — its features move.
const CHECKSUM_2: &str = "pub fn checksum(bytes: &[u8]) -> u32 {
let mut acc = 17u32;
for b in bytes {
acc = acc.rotate_left(5) ^ u32::from(*b);
}
acc.rotate_right(3)
}";
/// A function that appears at variant 3: the population moves.
const FOLD_BYTES: &str = "pub fn fold_bytes(bytes: &[u8], seed: u32) -> u32 {
let mut h = seed;
for b in bytes {
h = h.wrapping_mul(31).wrapping_add(u32::from(*b));
}
h
}";
/// One function: its text, params, the printed return type, and what it touches.
struct Fun {
name: &'static str,
text: String,
params: Vec<(&'static str, &'static str)>,
ret: Option<&'static str>,
uses: bool,
reads: Vec<&'static str>,
calls: Vec<String>,
}
fn funs(v: u8) -> Vec<Fun> {
let second = v >= 1;
let ml = |name, text: &str, params: Vec<(&'static str, &'static str)>, ret, reads: Vec<&'static str>| Fun { name, text: text.to_string(), params, ret, uses: true, reads, calls: Vec::new() };
let mut out = vec![
ml("tally", TALLY, vec![("layout", "&MapLayout"), ("floor", "u32")], Some("u32"), vec!["plates", "repos"]),
ml("summarize", if second { SUMMARIZE_2 } else { SUMMARIZE }, vec![("map", "&MapLayout"), ("min", "u32")], Some("u32"), vec!["plates", "repos"]),
ml("tally_more", TALLY_MORE, vec![("layout", "&MapLayout"), ("floor", "u32")], Some("u32"), vec!["plates", "repos"]),
ml("place", PLACE, vec![("seed", "&MapLayout"), ("extra", "u32")], Some("MapLayout"), vec!["repos", "plates"]),
ml("arrange", ARRANGE, vec![("base", "&MapLayout"), ("names", "&[String]")], Some("MapLayout"), vec!["plates", "repos"]),
Fun { name: "kill", text: KILL.into(), params: vec![("pid", "u32"), ("table", "&mut Vec<u32>")], ret: Some("bool"), uses: false, reads: vec![], calls: vec!["retain".into()] },
Fun { name: "delete", text: DELETE.into(), params: vec![("path", "&str"), ("cache", "&mut String")], ret: Some("usize"), uses: false, reads: vec![], calls: vec!["find".into(), "replace_range".into()] },
Fun { name: "now_ms", text: NOW_MS.into(), params: vec![], ret: Some("u64"), uses: false, reads: vec![], calls: vec!["now".into(), "duration_since".into(), "as_millis".into()] },
Fun { name: "now_unix_ms", text: NOW_UNIX_MS.into(), params: vec![], ret: Some("u64"), uses: false, reads: vec![], calls: vec!["now".into(), "duration_since".into(), "as_millis".into()] },
Fun { name: "workspace_root", text: WORKSPACE_ROOT.into(), params: vec![], ret: Some("PathBuf"), uses: false, reads: vec![], calls: vec!["from".into(), "parent".into(), "map".into(), "unwrap_or".into()] },
Fun { name: "repo_root", text: REPO_ROOT.into(), params: vec![], ret: Some("PathBuf"), uses: false, reads: vec![], calls: vec!["current_dir".into(), "unwrap_or_default".into(), "join".into(), "exists".into(), "pop".into()] },
Fun { name: "sum_lanes_avx2", text: sum_lanes("avx2"), params: vec![("xs", "&[u32]"), ("floor", "u32")], ret: Some("u32"), uses: false, reads: vec![], calls: vec!["len".into(), "wrapping_add".into()] },
Fun { name: "sum_lanes_scalar", text: sum_lanes("scalar"), params: vec![("xs", "&[u32]"), ("floor", "u32")], ret: Some("u32"), uses: false, reads: vec![], calls: vec!["len".into(), "wrapping_add".into()] },
Fun { name: "bump_alpha", text: bump("alpha"), params: vec![("xs", "&mut AlphaLanes"), ("by", "u16")], ret: Some("usize"), uses: false, reads: vec![], calls: vec!["alpha_iter".into(), "alpha_settle".into()] },
Fun { name: "bump_beta", text: bump("beta"), params: vec![("xs", "&mut BetaLanes"), ("by", "u8")], ret: Some("isize"), uses: false, reads: vec![], calls: vec!["beta_iter".into(), "beta_settle".into()] },
Fun { name: "flag_a", text: flag("a"), params: vec![], ret: Some("Option<bool>"), uses: false, reads: vec!["plates"], calls: vec![] },
Fun { name: "flag_b", text: flag("b"), params: vec![], ret: Some("Option<bool>"), uses: false, reads: vec!["plates"], calls: vec![] },
if v >= 2 {
Fun { name: "checksum", text: CHECKSUM_2.into(), params: vec![("bytes", "&[u8]")], ret: Some("u32"), uses: false, reads: vec![], calls: vec!["rotate_left".into(), "rotate_right".into()] }
} else {
Fun { name: "checksum", text: CHECKSUM.into(), params: vec![("bytes", "&[u8]")], ret: Some("u32"), uses: false, reads: vec![], calls: vec!["rotate_left".into()] }
},
];
if v >= 3 {
out.push(Fun { name: "fold_bytes", text: FOLD_BYTES.into(), params: vec![("bytes", "&[u8]"), ("seed", "u32")], ret: Some("u32"), uses: false, reads: vec![], calls: vec!["wrapping_mul".into(), "wrapping_add".into()] });
}
for i in 0..30 {
out.push(Fun {
name: Box::leak(format!("step{i}").into_boxed_str()),
text: format!("pub fn step{i}(name: &str) -> Result<(), Error> {{\n check{i}(name)?;\n Ok(())\n}}"),
params: vec![("name", "&str")],
ret: Some("Result<(), Error>"),
uses: false,
reads: vec![],
calls: vec![format!("check{i}")],
});
}
out
}
fn commit(root: &Path, v: u8) -> CommitDump {
let krate = clo("crate/");
let strukt = clo("MapLayout#");
let field = |f: &str| clo(&format!("MapLayout#{f}."));
let mut src = Source::default();
src.plain("//! clo\n\npub struct MapLayout {\n pub repos: Vec<String>,\n pub plates: Vec<u32>,\n}\n");
let fs = funs(v);
for f in &fs {
src.item(&clo(&format!("{}().", f.name)), 0, &f.text);
}
let spans = src.write(root, "src/lib.rs");
let mut nodes: Vec<N> = vec![
n(krate.clone(), "crate", Level::Crate, "clo", None),
n(strukt.clone(), "struct", Level::Item, "MapLayout", Some(krate.clone())),
n(field("repos"), "field", Level::Part, "repos", Some(strukt.clone())),
n(field("plates"), "field", Level::Part, "plates", Some(strukt.clone())),
];
let mut edges: Vec<EdgeRow> = vec![e(&krate, &strukt, EdgeKind::Contains, 1), e(&strukt, &field("repos"), EdgeKind::Contains, 1), e(&strukt, &field("plates"), EdgeKind::Contains, 1)];
let mut stubs = BTreeSet::new();
for f in &fs {
let id = clo(&format!("{}().", f.name));
let calls: Vec<&str> = f.calls.iter().map(String::as_str).collect();
callable(&mut nodes, &mut edges, &mut stubs, n(id.clone(), "fn", Level::Item, f.name, Some(krate.clone())), &krate, &f.params, &calls);
if let Some(ty) = f.ret {
let rid = format!("{id}`->`");
nodes.push(n(rid.clone(), "ret", Level::Part, "->", Some(id.clone())).ty(ty));
edges.push(e(&id, &rid, EdgeKind::Contains, 1));
}
if f.uses {
edges.push(e(&id, &strukt, EdgeKind::UsesType, 1));
}
for r in &f.reads {
edges.push(e(&id, &field(r), EdgeKind::ReadsField, 1));
}
}
stubs_into(&mut nodes, &stubs);
CommitDump {
toolchain: "nightly-fixture".into(),
workspace_crates: ["clo@0.1.0:lib".to_string()].into(),
workspace_targets: ["clo:lib".to_string()].into(),
failed_units: BTreeSet::new(),
owner_disambiguations: 0,
crates: vec![unit("clo@0.1.0:lib", nodes, edges, spans)],
binary: false,
binaries: vec![],
}
}
/// The workspace and its checkout.
pub struct Clo {
pub ws: Workspace,
root: PathBuf,
}
impl Clo {
pub fn checkout(&self) -> PathBuf {
self.root.join("src-clo")
}
pub fn at(&self) -> (i64, String) {
let log = self.ws.room.log().unwrap();
let o = log.block_on(log.offsets()).unwrap().remove(CLO).expect("clo is consumed");
(o.seq, o.sha)
}
/// The `clone_shapes` feed for `clo`, as the consumer runs it.
pub fn shapes(&self) -> crate::clone_signals::feed::ShapeRun {
let (seq, sha) = self.at();
let log = self.ws.room.log().unwrap();
crate::clone_signals::feed::shapes_member(&self.ws.warehouse, &log, CLO, &self.checkout(), seq, &sha).unwrap()
}
/// The raw vectors (the `embeddings` feed's function half) and the
/// normalised ones (`clone_shapes`' deferred half), both through `bag`.
pub fn embed(&self, bag: &super::vectors::Bag) -> crate::clone_signals::feed::NormRun {
let (seq, sha) = self.at();
let log = self.ws.room.log().unwrap();
let mut embedding = crate::vector::fnvec::Loaded { embedder: bag, backend: "test bag (cpu)" };
crate::vector::fnvec::room::embed_member_with(&self.ws.warehouse, &log, CLO, &self.checkout(), seq, &sha, &mut embedding).unwrap();
let chunks = crate::clone_signals::feed::read_chunks(&log, CLO, &self.checkout(), seq).unwrap();
crate::clone_signals::feed::embed_normalised(&self.ws.warehouse, &chunks, &mut embedding).unwrap()
}
/// Consume `clo`'s second commit: `summarize` gets another body.
pub fn second_commit(&self) {
self.commit_v(1);
}
/// Consume the next commit of `clo` at fixture variant `v` (module docs).
pub fn commit_v(&self, v: u8) {
let dir = self.checkout();
let dump = commit(&dir, v);
nornir_git::gitio::commit_all(&dir, &format!("variant {v}")).unwrap();
consume_next(&self.ws.room, &dir, CLO, dump);
}
}
/// `clo` consumed at its first commit; no shape, no vector yet.
pub fn build() -> Clo {
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("clones", &builds);
let dir = root.join("src-clo");
nornir_git::gitio::init(&dir).unwrap();
let dump = commit(&dir, 0);
nornir_git::gitio::commit_all(&dir, "first").unwrap();
consume_next(&room, &dir, CLO, dump);
Clo { ws: Workspace { room, warehouse, builds, _tmp: tmp }, root }
}