Rename cluster -> net

This commit is contained in:
Adam Gausmann 2022-11-06 19:22:57 -06:00
parent a1966cfc70
commit 5d063859d9
2 changed files with 52 additions and 60 deletions

View file

@ -12,13 +12,13 @@ use std::{
/// An in-memory representation of a Sandbox that is easy to modify. /// An in-memory representation of a Sandbox that is easy to modify.
pub struct Sandbox { pub struct Sandbox {
next_component: u32, next_component: u32,
next_cluster: u32, next_net: u32,
next_wire: u32, next_wire: u32,
next_type: u16, next_type: u16,
root_components: HashSet<ComponentId>, root_components: HashSet<ComponentId>,
components: HashMap<ComponentId, ComponentInfo>, components: HashMap<ComponentId, ComponentInfo>,
wires: HashMap<WireId, WireInfo>, wires: HashMap<WireId, WireInfo>,
clusters: HashMap<ClusterId, ClusterInfo>, nets: HashMap<NetId, NetInfo>,
component_types: HashMap<String, u16>, component_types: HashMap<String, u16>,
mods: Vec<ModInfo>, mods: Vec<ModInfo>,
} }
@ -33,13 +33,13 @@ impl Sandbox {
fn with_meta_info(component_types: HashMap<String, u16>, mods: Vec<ModInfo>) -> Self { fn with_meta_info(component_types: HashMap<String, u16>, mods: Vec<ModInfo>) -> Self {
Self { Self {
next_component: 1, next_component: 1,
next_cluster: 0, next_net: 0,
next_wire: 0, next_wire: 0,
next_type: component_types.values().copied().max().unwrap_or(0), next_type: component_types.values().copied().max().unwrap_or(0),
root_components: HashSet::new(), root_components: HashSet::new(),
components: HashMap::new(), components: HashMap::new(),
wires: HashMap::new(), wires: HashMap::new(),
clusters: HashMap::new(), nets: HashMap::new(),
component_types, component_types,
mods, mods,
} }
@ -53,13 +53,13 @@ impl Sandbox {
rotation: component.rotation, rotation: component.rotation,
children: HashSet::new(), children: HashSet::new(),
inputs: repeat_with(|| PegInfo { inputs: repeat_with(|| PegInfo {
cluster_id: self.make_cluster(), net_id: self.make_net(),
wires: HashSet::new(), wires: HashSet::new(),
}) })
.take(component.num_inputs as usize) .take(component.num_inputs as usize)
.collect(), .collect(),
outputs: repeat_with(|| PegInfo { outputs: repeat_with(|| PegInfo {
cluster_id: self.make_cluster(), net_id: self.make_net(),
wires: HashSet::new(), wires: HashSet::new(),
}) })
.take(component.num_outputs as usize) .take(component.num_outputs as usize)
@ -72,7 +72,7 @@ impl Sandbox {
} }
/// Internal logic of `add_component` that is shared with savefile loading. /// Internal logic of `add_component` that is shared with savefile loading.
/// Savefiles store the component and cluster IDs, so they can be directly /// Savefiles store the component and net IDs, so they can be directly
/// passed instead of being allocated (as is done by `add_component`). /// passed instead of being allocated (as is done by `add_component`).
fn insert_component(&mut self, id: ComponentId, info: ComponentInfo) { fn insert_component(&mut self, id: ComponentId, info: ComponentInfo) {
// TODO bubble this error (could be triggered by an invalid savefile). // TODO bubble this error (could be triggered by an invalid savefile).
@ -119,7 +119,7 @@ impl Sandbox {
addr_a: PegAddress, addr_a: PegAddress,
addr_b: PegAddress, addr_b: PegAddress,
rotation: f32, rotation: f32,
cluster_id: Option<ClusterId>, net_id: Option<NetId>,
) -> Result<WireId, AddWireError> { ) -> Result<WireId, AddWireError> {
// It is illegal to directly connect output pegs. // It is illegal to directly connect output pegs.
if addr_a.peg_type == PegType::Output && addr_b.peg_type == PegType::Output { if addr_a.peg_type == PegType::Output && addr_b.peg_type == PegType::Output {
@ -138,21 +138,21 @@ impl Sandbox {
return Ok(wire_id); return Ok(wire_id);
} }
let cluster_id = match cluster_id { let net_id = match net_id {
Some(id) => { Some(id) => {
// If cluster ID is specified (i.e. from an existing savefile), // If net ID is specified (i.e. from an existing savefile),
// check savefile validity: ensure that both endpoints and the // check savefile validity: ensure that both endpoints and the
// wire all have the same cluster. // wire all have the same net.
//TODO bubble this error //TODO bubble this error
assert!(id == peg_a.cluster_id && id == peg_b.cluster_id); assert!(id == peg_a.net_id && id == peg_b.net_id);
id id
} }
None => { None => {
// If no cluster ID is given (i.e. caller is `add_wire`), then // If no net ID is given (i.e. caller is `add_wire`), then
// obtain one from merging the two endpoints. // obtain one from merging the two endpoints.
self.merge_clusters(peg_a.cluster_id, peg_b.cluster_id) self.merge_nets(peg_a.net_id, peg_b.net_id)
} }
}; };
@ -164,19 +164,15 @@ impl Sandbox {
WireInfo { WireInfo {
a: addr_a, a: addr_a,
b: addr_b, b: addr_b,
cluster_id, net_id,
rotation, rotation,
}, },
); );
// Register wire references in pegs and cluster. // Register wire references in pegs and net.
self.get_peg_mut(&addr_a).unwrap().wires.insert(wire_id); self.get_peg_mut(&addr_a).unwrap().wires.insert(wire_id);
self.get_peg_mut(&addr_b).unwrap().wires.insert(wire_id); self.get_peg_mut(&addr_b).unwrap().wires.insert(wire_id);
self.clusters self.nets.get_mut(&net_id).unwrap().wires.insert(wire_id);
.get_mut(&cluster_id)
.unwrap()
.wires
.insert(wire_id);
Ok(wire_id) Ok(wire_id)
} }
@ -186,7 +182,7 @@ impl Sandbox {
// TODO Remove component. // TODO Remove component.
// TODO Remove peg-cluster cross-references. Remove clusters if empty. // TODO Remove peg-net cross-references. Remove nets if empty.
todo!() todo!()
} }
@ -201,16 +197,12 @@ impl Sandbox {
} }
}; };
// Remove wire-cluster and wire-peg cross-references. // Remove wire-net and wire-peg cross-references.
self.clusters self.nets.get_mut(&wire.net_id).unwrap().wires.remove(&id);
.get_mut(&wire.cluster_id)
.unwrap()
.wires
.remove(&id);
self.get_peg_mut(&wire.a).unwrap().wires.remove(&id); self.get_peg_mut(&wire.a).unwrap().wires.remove(&id);
self.get_peg_mut(&wire.b).unwrap().wires.remove(&id); self.get_peg_mut(&wire.b).unwrap().wires.remove(&id);
// Split cluster if necessary. // Split net if necessary.
self.check_split(&wire.a, &wire.b); self.check_split(&wire.a, &wire.b);
} }
@ -226,38 +218,38 @@ impl Sandbox {
} }
} }
fn make_cluster(&mut self) -> ClusterId { fn make_net(&mut self) -> NetId {
let id = ClusterId(self.next_cluster); let id = NetId(self.next_net);
self.next_cluster += 1; self.next_net += 1;
id id
} }
fn merge_clusters(&mut self, id_a: ClusterId, id_b: ClusterId) -> ClusterId { fn merge_nets(&mut self, id_a: NetId, id_b: NetId) -> NetId {
// Nothing needs to be done if the two clusters are the same. // Nothing needs to be done if the two nets are the same.
if id_a == id_b { if id_a == id_b {
return id_a; return id_a;
} }
let a = &self.clusters[&id_a]; let a = &self.nets[&id_a];
let b = &self.clusters[&id_b]; let b = &self.nets[&id_b];
// Merge the smaller cluster into the larger cluster. // Merge the smaller net into the larger net.
let (id_dest, id_src) = if a.size() >= b.size() { let (id_dest, id_src) = if a.size() >= b.size() {
(id_a, id_b) (id_a, id_b)
} else { } else {
(id_b, id_a) (id_b, id_a)
}; };
let src = self.clusters.remove(&id_src).unwrap(); let src = self.nets.remove(&id_src).unwrap();
// Update cluster cross-references: // Update net cross-references:
for wire_id in &src.wires { for wire_id in &src.wires {
self.wires.get_mut(wire_id).unwrap().cluster_id = id_dest; self.wires.get_mut(wire_id).unwrap().net_id = id_dest;
} }
for peg_id in &src.pegs { for peg_id in &src.pegs {
self.get_peg_mut(peg_id).unwrap().cluster_id = id_dest; self.get_peg_mut(peg_id).unwrap().net_id = id_dest;
} }
// Move references from src into dest: // Move references from src into dest:
let dest = self.clusters.get_mut(&id_dest).unwrap(); let dest = self.nets.get_mut(&id_dest).unwrap();
dest.pegs.extend(src.pegs); dest.pegs.extend(src.pegs);
dest.wires.extend(src.wires); dest.wires.extend(src.wires);
@ -265,9 +257,9 @@ impl Sandbox {
} }
fn check_split(&mut self, addr_a: &PegAddress, addr_b: &PegAddress) { fn check_split(&mut self, addr_a: &PegAddress, addr_b: &PegAddress) {
// Traverse the whole cluster connected to addr_a. // Traverse the whole net connected to addr_a.
// If addr_b is in that set, then they are connected. // If addr_b is in that set, then they are connected.
// If not, a new cluster needs to be created. // If not, a new net needs to be created.
let mut frontier = Vec::new(); let mut frontier = Vec::new();
let mut visited_pegs = HashSet::new(); let mut visited_pegs = HashSet::new();
@ -297,14 +289,14 @@ impl Sandbox {
return; return;
} }
// B is not connected to A; make a new cluster and update all the // B is not connected to A; make a new net and update all the
// pegs and wires found connected to A. // pegs and wires found connected to A.
let cluster_id = self.make_cluster(); let net_id = self.make_net();
for peg_addr in visited_pegs { for peg_addr in visited_pegs {
self.get_peg_mut(&peg_addr).unwrap().cluster_id = cluster_id; self.get_peg_mut(&peg_addr).unwrap().net_id = net_id;
} }
for wire_id in visited_wires { for wire_id in visited_wires {
self.wires.get_mut(&wire_id).unwrap().cluster_id = cluster_id; self.wires.get_mut(&wire_id).unwrap().net_id = net_id;
} }
} }
@ -390,9 +382,9 @@ impl ComponentId {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ClusterId(u32); pub struct NetId(u32);
impl ClusterId { impl NetId {
fn into_raw(self) -> i32 { fn into_raw(self) -> i32 {
self.0.try_into().unwrap() self.0.try_into().unwrap()
} }
@ -451,7 +443,7 @@ impl ComponentInfo {
} }
struct PegInfo { struct PegInfo {
cluster_id: ClusterId, net_id: NetId,
wires: HashSet<WireId>, wires: HashSet<WireId>,
} }
@ -459,16 +451,16 @@ struct PegInfo {
struct WireInfo { struct WireInfo {
a: PegAddress, a: PegAddress,
b: PegAddress, b: PegAddress,
cluster_id: ClusterId, net_id: NetId,
rotation: f32, rotation: f32,
} }
struct ClusterInfo { struct NetInfo {
wires: HashSet<WireId>, wires: HashSet<WireId>,
pegs: HashSet<PegAddress>, pegs: HashSet<PegAddress>,
} }
impl ClusterInfo { impl NetInfo {
fn size(&self) -> usize { fn size(&self) -> usize {
self.wires.len() + self.pegs.len() self.wires.len() + self.pegs.len()
} }

View file

@ -67,7 +67,7 @@ impl From<&blotter::BlotterFile> for super::Sandbox {
wire.start_peg.into(), wire.start_peg.into(),
wire.end_peg.into(), wire.end_peg.into(),
wire.rotation, wire.rotation,
Some(super::ClusterId::from_raw(wire.circuit_state_id)), Some(super::NetId::from_raw(wire.circuit_state_id)),
) )
.unwrap(); .unwrap();
} }
@ -117,7 +117,7 @@ impl From<&blotter::Component> for (super::ComponentId, super::ComponentInfo) {
impl From<&super::PegInfo> for blotter::Input { impl From<&super::PegInfo> for blotter::Input {
fn from(peg: &super::PegInfo) -> Self { fn from(peg: &super::PegInfo) -> Self {
Self { Self {
circuit_state_id: peg.cluster_id.into_raw(), circuit_state_id: peg.net_id.into_raw(),
} }
} }
} }
@ -125,7 +125,7 @@ impl From<&super::PegInfo> for blotter::Input {
impl From<&blotter::Input> for super::PegInfo { impl From<&blotter::Input> for super::PegInfo {
fn from(input: &blotter::Input) -> Self { fn from(input: &blotter::Input) -> Self {
Self { Self {
cluster_id: super::ClusterId::from_raw(input.circuit_state_id), net_id: super::NetId::from_raw(input.circuit_state_id),
wires: HashSet::new(), wires: HashSet::new(),
} }
} }
@ -134,7 +134,7 @@ impl From<&blotter::Input> for super::PegInfo {
impl From<&super::PegInfo> for blotter::Output { impl From<&super::PegInfo> for blotter::Output {
fn from(peg: &super::PegInfo) -> Self { fn from(peg: &super::PegInfo) -> Self {
Self { Self {
circuit_state_id: peg.cluster_id.into_raw(), circuit_state_id: peg.net_id.into_raw(),
} }
} }
} }
@ -142,7 +142,7 @@ impl From<&super::PegInfo> for blotter::Output {
impl From<&blotter::Output> for super::PegInfo { impl From<&blotter::Output> for super::PegInfo {
fn from(input: &blotter::Output) -> Self { fn from(input: &blotter::Output) -> Self {
Self { Self {
cluster_id: super::ClusterId::from_raw(input.circuit_state_id), net_id: super::NetId::from_raw(input.circuit_state_id),
wires: HashSet::new(), wires: HashSet::new(),
} }
} }
@ -153,7 +153,7 @@ impl From<&super::WireInfo> for blotter::Wire {
Self { Self {
start_peg: wire.a.into(), start_peg: wire.a.into(),
end_peg: wire.b.into(), end_peg: wire.b.into(),
circuit_state_id: wire.cluster_id.into_raw(), circuit_state_id: wire.net_id.into_raw(),
rotation: wire.rotation, rotation: wire.rotation,
} }
} }