Skip to content

Commit

Permalink
#49: uni.slice
Browse files Browse the repository at this point in the history
  • Loading branch information
yegor256 committed Sep 28, 2022
1 parent c8d21fd commit b0192c0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 6 deletions.
68 changes: 65 additions & 3 deletions src/universe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ use crate::data::Data;
use anyhow::Result;
use log::error;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::fmt;

#[derive(Serialize, Deserialize, Eq, PartialOrd, PartialEq, Ord)]
#[derive(Clone, Serialize, Deserialize, Eq, PartialOrd, PartialEq, Ord)]
struct Edge {
from: u32,
to: u32,
Expand Down Expand Up @@ -156,7 +156,7 @@ impl Universe {
self.atoms.insert(name.to_string(), m);
}

/// Merge universe into inself
/// Merge this new universe into itself.
pub fn merge(&mut self, uni: &Universe) {
let mut matcher: HashMap<u32, u32> = HashMap::new();
for vert in uni.vertices.iter() {
Expand All @@ -178,6 +178,55 @@ impl Universe {
}
}

/// Take a slice of the universe, keeping only the vertex specified
/// by the locator.
pub fn slice(&mut self, loc: String) -> Result<Universe> {
let mut todo = HashSet::new();
let mut done = HashSet::new();
todo.insert(self.find(0, loc.as_str())?);
loop {
if todo.is_empty() {
break;
}
let before: Vec<u32> = todo.drain().collect();
for v in before {
done.insert(v);
for to in self
.edges
.values()
.filter(|e| e.a != "ρ" && e.a != "σ")
.filter(|e| e.from == v)
.map(|e| e.to)
{
if done.contains(&to) {
continue;
}
done.insert(to);
todo.insert(to);
}
}
}
let mut new_vertices = HashMap::new();
for (v, vtx) in self.vertices.iter().filter(|(v, _)| done.contains(v)) {
new_vertices.insert(*v, vtx.clone());
}
let mut new_edges = HashMap::new();
for (e, edge) in self
.edges
.iter()
.filter(|(_, edge)| done.contains(&edge.from) || done.contains(&edge.to))
{
new_edges.insert(*e, edge.clone());
}
Ok(Universe {
vertices: new_vertices,
edges: new_edges,
atoms: HashMap::new(),
latest_v: self.latest_v,
latest_e: self.latest_e,
})
}

/// Validate the Universe and return all found data
/// inconsistencies. This is mostly used for testing.
pub fn inconsistencies(&self) -> Vec<String> {
Expand Down Expand Up @@ -243,3 +292,16 @@ fn generates_random_int() -> Result<()> {
assert_ne!(first, second);
Ok(())
}

#[test]
fn makes_a_slice() -> Result<()> {
let mut uni = Universe::empty();
uni.add(0)?;
let v1 = add!(uni);
bind!(uni, 0, v1, "foo");
let v2 = add!(uni);
bind!(uni, 0, v2, "bar");
let slice = uni.slice("Φ.bar".to_string())?;
assert_eq!(1, slice.vertices.len());
Ok(())
}
6 changes: 4 additions & 2 deletions src/universe/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ impl Universe {
}
if let Some(d) = &(*vtx).data {
let mut data_node = XMLElement::new("data");
data_node.add_text(d.as_hex()).unwrap();
data_node
.add_text(format!("bytes/{}", d.as_hex().replace(' ', "-")))
.unwrap();
v_node.add_child(data_node).unwrap();
}
if !vtx.lambda_name.is_empty() {
Expand Down Expand Up @@ -88,7 +90,7 @@ fn prints_simple_graph() -> Result<()> {
evaluate_xpath(&doc, "/graph/v[@id=1]/lambda")?.string()
);
assert_eq!(
"00-00-00-00-00-00-00-2A",
"bytes/00-00-00-00-00-00-00-2A",
evaluate_xpath(&doc, "/graph/v[@id=0]/data")?.string()
);
Ok(())
Expand Down
3 changes: 2 additions & 1 deletion tests/snippets_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ fn deploys_and_runs_all_apps() -> Result<()> {
.assert()
.success();
let mut uni = Universe::load(relf)?;
println!("{}", uni.inspect("Q.org.eolang.reo")?);
for app in all_apps()? {
println!("{}", uni.inspect(format!("Q.{}", app).as_str())?);
println!("{}", uni.slice(format!("Q.{}", app))?.to_graph()?);
let expected = da!(uni, format!("Φ.{}.expected", app));
let actual = da!(uni, format!("Φ.{}", app));
assert_eq!(expected, actual);
Expand Down

0 comments on commit b0192c0

Please sign in to comment.