WIP Skeleton implementation

This commit is contained in:
Tony Garnock-Jones 2019-10-20 22:25:01 +01:00
parent 4eb35ca9b8
commit 3d48cebb91
2 changed files with 252 additions and 60 deletions

View File

@ -1,6 +1,7 @@
use super::V;
use super::ConnId;
use super::packets;
use super::skeleton;
use preserves::value::Map;
use std::sync::{Arc, RwLock};
@ -21,11 +22,12 @@ impl From<DataspaceError> for std::io::Error {
pub struct Dataspace {
name: V,
peers: Map<ConnId, UnboundedSender<packets::Out>>,
index: skeleton::Index,
}
impl Dataspace {
pub fn new(name: &V) -> Self {
Self { name: name.clone(), peers: Map::new() }
Self { name: name.clone(), peers: Map::new(), index: skeleton::Index::new() }
}
pub fn new_ref(name: &V) -> DataspaceRef {

View File

@ -1,74 +1,264 @@
// pub type V = preserves::value::ArcValue;
use super::ConnId;
use super::packets::Assertion;
use super::packets::Captures;
use super::packets::EndpointName;
use super::packets::Event;
// type Map<A,B> = std::collections::BTreeMap<A,B>;
// type Set<A> = std::collections::BTreeSet<A>;
// type Bag<A> = super::bag::BTreeBag<A>;
use preserves::value::{Map, Set, Value, NestedValue};
use std::collections::btree_map::Entry;
// pub enum Event {
// Removed,
// Message,
// Added,
// }
type Bag<A> = super::bag::BTreeBag<A>;
// type Path = Vec<usize>;
// type Paths = Vec<Path>;
// type Captures = Vec<V>;
type Path = Vec<usize>;
type Paths = Vec<Path>;
// trait HandleEvent {
// fn handle_event<'a>(self, captures: &Captures);
// }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Endpoint {
connection: ConnId,
name: EndpointName,
}
// pub enum Skeleton {
// Blank,
// Guarded(Guard, Vec<Skeleton>)
// }
pub enum Skeleton {
Blank,
Guarded(Guard, Vec<Skeleton>)
}
// pub struct AnalysisResults {
// skeleton: Skeleton,
// const_paths: Paths,
// const_vals: Vec<V>,
// capture_paths: Paths,
// assertion: V,
// }
pub struct AnalysisResults {
skeleton: Skeleton,
const_paths: Paths,
const_vals: Vec<Assertion>,
capture_paths: Paths,
assertion: Assertion,
}
// pub struct Index {
// all_assertions: Bag<V>,
// }
#[derive(Debug)]
pub struct Index {
all_assertions: Bag<Assertion>,
root: Node,
}
// impl Index {
// pub fn new() -> Self {
// Index{ all_assertions: Bag::new() }
// }
impl Index {
pub fn new() -> Self {
Index{ all_assertions: Bag::new(), root: Node::new(Continuation::new(Set::new())) }
}
// // pub fn add_handler(analysis_results: AnalysisResults,
// }
pub fn add_endpoint(&mut self, analysis_results: AnalysisResults, endpoint: Endpoint)
-> Vec<Event>
{
let continuation = self.root.extend(&analysis_results.skeleton);
let continuation_cached_assertions = &continuation.cached_assertions;
let const_val_map =
continuation.leaf_map.entry(analysis_results.const_paths.clone()).or_insert_with(|| {
let mut cvm = Map::new();
for a in continuation_cached_assertions {
let key = project_paths(a.unscope(), &analysis_results.const_paths);
cvm.entry(key).or_insert_with(Leaf::new).cached_assertions.insert(a.clone());
}
cvm
});
let capture_paths = analysis_results.capture_paths;
let leaf = const_val_map.entry(analysis_results.const_vals).or_insert_with(Leaf::new);
let leaf_cached_assertions = &leaf.cached_assertions;
let endpoints = leaf.endpoints_map.entry(capture_paths.clone()).or_insert_with(|| {
let mut b = Bag::new();
for a in leaf_cached_assertions {
let (restriction_paths, term) = a.unpack();
if is_unrestricted(&capture_paths, restriction_paths) {
let captures = project_paths(term, &capture_paths);
*b.entry(captures).or_insert(0) += 1;
}
}
Endpoints::new(b)
});
let endpoint_name = endpoint.name.clone();
endpoints.endpoints.insert(endpoint);
endpoints.cached_captures.into_iter()
.map(|(cs,_)| Event::Add(endpoint_name.clone(), cs.clone()))
.collect()
}
// struct Node {
// continuation: Continuation,
// edges: Map<Selector, Map<Guard, Node>>,
// }
pub fn remove_endpoint(&mut self, analysis_results: AnalysisResults, endpoint: Endpoint) {
let continuation = self.root.extend(&analysis_results.skeleton);
if let Entry::Occupied(mut const_val_map_entry)
= continuation.leaf_map.entry(analysis_results.const_paths)
{
let const_val_map = const_val_map_entry.get_mut();
if let Entry::Occupied(mut leaf_entry)
= const_val_map.entry(analysis_results.const_vals)
{
let leaf = leaf_entry.get_mut();
if let Entry::Occupied(mut endpoints_entry)
= leaf.endpoints_map.entry(analysis_results.capture_paths)
{
let endpoints = endpoints_entry.get_mut();
endpoints.endpoints.remove(&endpoint);
if endpoints.endpoints.is_empty() {
endpoints_entry.remove_entry();
}
}
if leaf.is_empty() {
leaf_entry.remove_entry();
}
}
if const_val_map.is_empty() {
const_val_map_entry.remove_entry();
}
}
}
}
// struct Continuation {
// cached_assertions: Set<V>,
// leaf_map: Map<Paths, Map<Vec<V>, Leaf>>,
// }
#[derive(Debug)]
struct Node {
continuation: Continuation,
edges: Map<Selector, Map<Guard, Node>>,
}
// struct Selector {
// pop_count: usize,
// index: usize,
// }
impl Node {
fn new(continuation: Continuation) -> Self {
Node { continuation, edges: Map::new() }
}
// pub enum Guard {
// Rec(V, usize),
// Seq(usize),
// }
fn extend(&mut self, skeleton: &Skeleton) -> &mut Continuation {
let (_pop_count, final_node) = self.extend_walk(&mut Vec::new(), 0, 0, skeleton);
&mut final_node.continuation
}
// struct Leaf { // aka Topic
// cached_assertions: Set<V>,
// handler_map: Map<Paths, Handler>,
// }
fn extend_walk(&mut self, path: &mut Path, pop_count: usize, index: usize, skeleton: &Skeleton)
-> (usize, &mut Node) {
match skeleton {
Skeleton::Blank => (pop_count, self),
Skeleton::Guarded(cls, kids) => {
let selector = Selector { pop_count, index };
let continuation = &self.continuation;
let table = self.edges.entry(selector).or_insert_with(Map::new);
let mut next_node = table.entry(cls.clone()).or_insert_with(|| {
Self::new(Continuation::new(
continuation.cached_assertions.iter()
.filter(|a| {
Some(cls) == class_of(project_path(a.unscope(), path)).as_ref() })
.cloned()
.collect()))
});
let mut pop_count = 0;
for (index, kid) in kids.iter().enumerate() {
path.push(index);
let (pc, nn) = next_node.extend_walk(path, pop_count, index, kid);
pop_count = pc;
next_node = nn;
path.pop();
}
(pop_count + 1, next_node)
}
}
}
}
// struct Handler {
// cached_captures: Bag<Captures>,
// callbacks: Set<Box<dyn HandleEvent>>,
// }
fn class_of(v: &Assertion) -> Option<Guard> {
match v.value() {
Value::Sequence(ref vs) => Some(Guard::Seq(vs.len())),
Value::Record((ref l, ref fs)) => Some(Guard::Rec(l.clone(), fs.len())),
_ => None,
}
}
fn project_path<'a>(v: &'a Assertion, p: &Path) -> &'a Assertion {
let mut v = v;
for i in p {
v = step(v, *i);
}
v
}
fn project_paths<'a>(v: &'a Assertion, ps: &Paths) -> Vec<Assertion> {
ps.iter().map(|p| project_path(v, p)).cloned().collect()
}
fn step(v: &Assertion, i: usize) -> &Assertion {
match v.value() {
Value::Sequence(ref vs) => &vs[i],
Value::Record((_, ref fs)) => &fs[i],
_ => panic!("step: non-sequence, non-record {:?}", v)
}
}
#[derive(Debug)]
struct Continuation {
cached_assertions: Set<CachedAssertion>,
leaf_map: Map<Paths, Map<Vec<Assertion>, Leaf>>,
}
impl Continuation {
fn new(cached_assertions: Set<CachedAssertion>) -> Self {
Continuation { cached_assertions, leaf_map: Map::new() }
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Selector {
pop_count: usize,
index: usize,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Guard {
Rec(Assertion, usize),
Seq(usize),
}
#[derive(Debug)]
struct Leaf { // aka Topic
cached_assertions: Set<CachedAssertion>,
endpoints_map: Map<Paths, Endpoints>,
}
impl Leaf {
fn new() -> Self {
Leaf { cached_assertions: Set::new(), endpoints_map: Map::new() }
}
fn is_empty(&self) -> bool {
self.cached_assertions.is_empty() && self.endpoints_map.is_empty()
}
}
#[derive(Debug)]
struct Endpoints {
cached_captures: Bag<Captures>,
endpoints: Set<Endpoint>,
}
impl Endpoints {
fn new(cached_captures: Bag<Captures>) -> Self {
Endpoints { cached_captures, endpoints: Set::new() }
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
enum CachedAssertion {
VisibilityRestricted(Paths, Assertion),
Unrestricted(Assertion),
}
impl CachedAssertion {
fn unscope(&self) -> &Assertion {
match self {
CachedAssertion::VisibilityRestricted(_, a) => a,
CachedAssertion::Unrestricted(a) => a,
}
}
fn unpack(&self) -> (Option<&Paths>, &Assertion) {
match self {
CachedAssertion::VisibilityRestricted(ps, a) => (Some(ps), a),
CachedAssertion::Unrestricted(a) => (None, a),
}
}
}
fn is_unrestricted(capture_paths: &Paths, restriction_paths: Option<&Paths>) -> bool {
if restriction_paths.is_none() {
return false;
}
panic!("Not yet implemented");
}