Progress on skeleton impl
This commit is contained in:
parent
3d48cebb91
commit
e5afef28cc
|
@ -5,9 +5,9 @@ authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
preserves = "0.2.3"
|
||||
preserves = "0.3.0"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_bytes = "0.11"
|
||||
|
||||
tokio = "0.2.0-alpha"
|
||||
|
|
|
@ -2,8 +2,9 @@ use std::collections::BTreeMap;
|
|||
use std::collections::btree_map::{Iter, Keys, Entry};
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
|
||||
type Count = i32;
|
||||
pub type Count = i32;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Net {
|
||||
PresentToAbsent,
|
||||
AbsentToAbsent,
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -11,8 +11,24 @@ use preserves::value;
|
|||
use std::sync::{Mutex, Arc};
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Syndicate {
|
||||
Placeholder(usize),
|
||||
}
|
||||
|
||||
impl value::Domain for Syndicate {}
|
||||
|
||||
static NEXT_PLACEHOLDER: AtomicUsize = AtomicUsize::new(0);
|
||||
impl Syndicate {
|
||||
pub fn new_placeholder() -> Self {
|
||||
Self::Placeholder(NEXT_PLACEHOLDER.fetch_add(1, Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
pub type ConnId = u64;
|
||||
pub type V = value::ArcValue;
|
||||
pub type V = value::ArcValue<Syndicate>;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use super::V;
|
||||
use super::Syndicate;
|
||||
|
||||
use bytes::BytesMut;
|
||||
use preserves::value;
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type EndpointName = V;
|
||||
pub type Assertion = V;
|
||||
pub type Captures = Vec<Assertion>;
|
||||
pub type Captures = Arc<Vec<Assertion>>;
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Action {
|
||||
|
@ -44,7 +46,7 @@ pub enum Out {
|
|||
#[derive(Debug)]
|
||||
pub enum DecodeError {
|
||||
Read(value::decoder::Error),
|
||||
Parse(value::error::Error, V),
|
||||
Parse(value::error::Error<Syndicate>, V),
|
||||
}
|
||||
|
||||
impl From<io::Error> for DecodeError {
|
||||
|
@ -58,7 +60,7 @@ impl From<io::Error> for DecodeError {
|
|||
#[derive(Debug)]
|
||||
pub enum EncodeError {
|
||||
Write(value::encoder::Error),
|
||||
Unparse(value::error::Error),
|
||||
Unparse(value::error::Error<Syndicate>),
|
||||
}
|
||||
|
||||
impl From<io::Error> for EncodeError {
|
||||
|
@ -67,8 +69,8 @@ impl From<io::Error> for EncodeError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<value::error::Error> for EncodeError {
|
||||
fn from(v: value::error::Error) -> Self {
|
||||
impl From<value::error::Error<Syndicate>> for EncodeError {
|
||||
fn from(v: value::error::Error<Syndicate>) -> Self {
|
||||
EncodeError::Unparse(v)
|
||||
}
|
||||
}
|
||||
|
@ -86,11 +88,11 @@ impl From<EncodeError> for io::Error {
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
pub struct Codec {
|
||||
codec: value::Codec<V>,
|
||||
codec: value::Codec<V, Syndicate>,
|
||||
}
|
||||
|
||||
impl Codec {
|
||||
pub fn new(codec: value::Codec<V>) -> Self {
|
||||
pub fn new(codec: value::Codec<V, Syndicate>) -> Self {
|
||||
Codec { codec }
|
||||
}
|
||||
}
|
||||
|
|
303
src/skeleton.rs
303
src/skeleton.rs
|
@ -1,4 +1,6 @@
|
|||
use super::ConnId;
|
||||
use super::Syndicate;
|
||||
use super::bag;
|
||||
use super::packets::Assertion;
|
||||
use super::packets::Captures;
|
||||
use super::packets::EndpointName;
|
||||
|
@ -6,13 +8,16 @@ use super::packets::Event;
|
|||
|
||||
use preserves::value::{Map, Set, Value, NestedValue};
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
type Bag<A> = super::bag::BTreeBag<A>;
|
||||
type Bag<A> = bag::BTreeBag<A>;
|
||||
|
||||
type Path = Vec<usize>;
|
||||
type Paths = Vec<Path>;
|
||||
type Events = Vec<(Vec<Endpoint>, Captures)>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct Endpoint {
|
||||
connection: ConnId,
|
||||
name: EndpointName,
|
||||
|
@ -24,16 +29,16 @@ pub enum Skeleton {
|
|||
}
|
||||
|
||||
pub struct AnalysisResults {
|
||||
skeleton: Skeleton,
|
||||
const_paths: Paths,
|
||||
const_vals: Vec<Assertion>,
|
||||
capture_paths: Paths,
|
||||
assertion: Assertion,
|
||||
pub skeleton: Skeleton,
|
||||
pub const_paths: Paths,
|
||||
pub const_vals: Captures,
|
||||
pub capture_paths: Paths,
|
||||
pub assertion: Assertion,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Index {
|
||||
all_assertions: Bag<Assertion>,
|
||||
all_assertions: Bag<CachedAssertion>,
|
||||
root: Node,
|
||||
}
|
||||
|
||||
|
@ -105,6 +110,61 @@ impl Index {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, v: CachedAssertion) -> Events {
|
||||
self.adjust(v, 1)
|
||||
}
|
||||
|
||||
fn remove(&mut self, v: CachedAssertion) -> Events {
|
||||
self.adjust(v, -1)
|
||||
}
|
||||
|
||||
fn adjust(&mut self, outer_value: CachedAssertion, delta: bag::Count) -> Events {
|
||||
let mut outputs = Vec::new();
|
||||
let net = self.all_assertions.change(outer_value.clone(), delta);
|
||||
match net {
|
||||
bag::Net::AbsentToPresent => {
|
||||
Modification::new(
|
||||
true,
|
||||
&outer_value,
|
||||
|c, v| { c.cached_assertions.insert(v.clone()); },
|
||||
|l, v| { l.cached_assertions.insert(v.clone()); },
|
||||
|es, cs| {
|
||||
if es.cached_captures.change(cs.clone(), 1) == bag::Net::AbsentToPresent {
|
||||
outputs.push((es.endpoints.iter().cloned().collect(), cs.clone()))
|
||||
}
|
||||
})
|
||||
.perform(&mut self.root);
|
||||
}
|
||||
bag::Net::PresentToAbsent => {
|
||||
Modification::new(
|
||||
false,
|
||||
&outer_value,
|
||||
|c, v| { c.cached_assertions.remove(v); },
|
||||
|l, v| { l.cached_assertions.remove(v); },
|
||||
|es, cs| {
|
||||
if es.cached_captures.change(cs.clone(), -1) == bag::Net::PresentToAbsent {
|
||||
outputs.push((es.endpoints.iter().cloned().collect(), cs.clone()))
|
||||
}
|
||||
})
|
||||
.perform(&mut self.root);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
outputs
|
||||
}
|
||||
|
||||
fn send(&mut self, outer_value: CachedAssertion) -> Events {
|
||||
let mut outputs = Vec::new();
|
||||
Modification::new(
|
||||
false,
|
||||
&outer_value,
|
||||
|_c, _v| (),
|
||||
|_l, _v| (),
|
||||
|es, cs| outputs.push((es.endpoints.iter().cloned().collect(), cs.clone())))
|
||||
.perform(&mut self.root);
|
||||
outputs
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -153,6 +213,114 @@ impl Node {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Stack<'a, T> {
|
||||
Empty,
|
||||
Item(T, &'a Stack<'a, T>)
|
||||
}
|
||||
|
||||
impl<'a, T> Stack<'a, T> {
|
||||
fn pop(&self) -> &Self {
|
||||
match self {
|
||||
Stack::Empty => panic!("Internal error: pop: Incorrect pop_count computation"),
|
||||
Stack::Item(_, tail) => tail
|
||||
}
|
||||
}
|
||||
|
||||
fn top(&self) -> &T {
|
||||
match self {
|
||||
Stack::Empty => panic!("Internal error: top: Incorrect pop_count computation"),
|
||||
Stack::Item(item, _) => item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Modification<'op, FCont, FLeaf, FEndpoints>
|
||||
where FCont: FnMut(&mut Continuation, &CachedAssertion) -> (),
|
||||
FLeaf: FnMut(&mut Leaf, &CachedAssertion) -> (),
|
||||
FEndpoints: FnMut(&mut Endpoints, Captures) -> ()
|
||||
{
|
||||
create_leaf_if_absent: bool,
|
||||
outer_value: &'op CachedAssertion,
|
||||
restriction_paths: Option<&'op Paths>,
|
||||
outer_value_term: &'op Assertion,
|
||||
m_cont: FCont,
|
||||
m_leaf: FLeaf,
|
||||
m_endpoints: FEndpoints,
|
||||
}
|
||||
|
||||
impl<'op, FCont, FLeaf, FEndpoints> Modification<'op, FCont, FLeaf, FEndpoints>
|
||||
where FCont: FnMut(&mut Continuation, &CachedAssertion) -> (),
|
||||
FLeaf: FnMut(&mut Leaf, &CachedAssertion) -> (),
|
||||
FEndpoints: FnMut(&mut Endpoints, Captures) -> ()
|
||||
{
|
||||
fn new(create_leaf_if_absent: bool,
|
||||
outer_value: &'op CachedAssertion,
|
||||
m_cont: FCont,
|
||||
m_leaf: FLeaf,
|
||||
m_endpoints: FEndpoints) -> Self {
|
||||
let (restriction_paths, outer_value_term) = outer_value.unpack();
|
||||
Modification {
|
||||
create_leaf_if_absent,
|
||||
outer_value,
|
||||
restriction_paths,
|
||||
outer_value_term,
|
||||
m_cont,
|
||||
m_leaf,
|
||||
m_endpoints,
|
||||
}
|
||||
}
|
||||
|
||||
fn perform(&mut self, n: &mut Node) {
|
||||
self.node(n, &Stack::Item(self.outer_value_term, &Stack::Empty))
|
||||
}
|
||||
|
||||
fn node(&mut self, n: &mut Node, term_stack: &Stack<&Assertion>) {
|
||||
self.continuation(&mut n.continuation);
|
||||
for (selector, table) in &mut n.edges {
|
||||
let mut next_stack = term_stack;
|
||||
for _ in 0..selector.pop_count { next_stack = next_stack.pop() }
|
||||
let next_value = step(next_stack.top(), selector.index);
|
||||
if let Some(next_class) = class_of(next_value) {
|
||||
if let Some(next_node) = table.get_mut(&next_class) {
|
||||
self.node(next_node, &Stack::Item(next_value, next_stack))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn continuation(&mut self, c: &mut Continuation) {
|
||||
(self.m_cont)(c, self.outer_value);
|
||||
let mut empty_const_paths = Vec::new();
|
||||
for (const_paths, const_val_map) in &mut c.leaf_map {
|
||||
let const_vals = project_paths(self.outer_value_term, const_paths);
|
||||
let leaf_opt = if self.create_leaf_if_absent {
|
||||
Some(const_val_map.entry(const_vals.clone()).or_insert_with(Leaf::new))
|
||||
} else {
|
||||
const_val_map.get_mut(&const_vals)
|
||||
};
|
||||
if let Some(leaf) = leaf_opt {
|
||||
(self.m_leaf)(leaf, self.outer_value);
|
||||
for (capture_paths, endpoints) in &mut leaf.endpoints_map {
|
||||
if is_unrestricted(&capture_paths, self.restriction_paths) {
|
||||
(self.m_endpoints)(endpoints,
|
||||
project_paths(self.outer_value_term, &capture_paths));
|
||||
}
|
||||
}
|
||||
if leaf.is_empty() {
|
||||
const_val_map.remove(&const_vals);
|
||||
if const_val_map.is_empty() {
|
||||
empty_const_paths.push(const_paths.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for const_paths in empty_const_paths {
|
||||
c.leaf_map.remove(&const_paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn class_of(v: &Assertion) -> Option<Guard> {
|
||||
match v.value() {
|
||||
Value::Sequence(ref vs) => Some(Guard::Seq(vs.len())),
|
||||
|
@ -169,8 +337,8 @@ fn project_path<'a>(v: &'a Assertion, p: &Path) -> &'a Assertion {
|
|||
v
|
||||
}
|
||||
|
||||
fn project_paths<'a>(v: &'a Assertion, ps: &Paths) -> Vec<Assertion> {
|
||||
ps.iter().map(|p| project_path(v, p)).cloned().collect()
|
||||
fn project_paths<'a>(v: &'a Assertion, ps: &Paths) -> Captures {
|
||||
Arc::new(ps.iter().map(|p| project_path(v, p)).cloned().collect())
|
||||
}
|
||||
|
||||
fn step(v: &Assertion, i: usize) -> &Assertion {
|
||||
|
@ -184,7 +352,7 @@ fn step(v: &Assertion, i: usize) -> &Assertion {
|
|||
#[derive(Debug)]
|
||||
struct Continuation {
|
||||
cached_assertions: Set<CachedAssertion>,
|
||||
leaf_map: Map<Paths, Map<Vec<Assertion>, Leaf>>,
|
||||
leaf_map: Map<Paths, Map<Captures, Leaf>>,
|
||||
}
|
||||
|
||||
impl Continuation {
|
||||
|
@ -205,6 +373,15 @@ pub enum Guard {
|
|||
Seq(usize),
|
||||
}
|
||||
|
||||
impl Guard {
|
||||
fn arity(&self) -> usize {
|
||||
match self {
|
||||
Guard::Rec(_, s) => *s,
|
||||
Guard::Seq(s) => *s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Leaf { // aka Topic
|
||||
cached_assertions: Set<CachedAssertion>,
|
||||
|
@ -234,7 +411,7 @@ impl Endpoints {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
enum CachedAssertion {
|
||||
pub enum CachedAssertion {
|
||||
VisibilityRestricted(Paths, Assertion),
|
||||
Unrestricted(Assertion),
|
||||
}
|
||||
|
@ -262,3 +439,105 @@ fn is_unrestricted(capture_paths: &Paths, restriction_paths: Option<&Paths>) ->
|
|||
|
||||
panic!("Not yet implemented");
|
||||
}
|
||||
|
||||
pub struct Analyzer {
|
||||
const_paths: Paths,
|
||||
const_vals: Vec<Assertion>,
|
||||
capture_paths: Paths,
|
||||
path: Path,
|
||||
}
|
||||
|
||||
impl Analyzer {
|
||||
pub fn analyze(a: &Assertion) -> AnalysisResults {
|
||||
let mut z = Analyzer {
|
||||
const_paths: Vec::new(),
|
||||
const_vals: Vec::new(),
|
||||
capture_paths: Vec::new(),
|
||||
path: Vec::new(),
|
||||
};
|
||||
let skeleton = z.walk(a);
|
||||
AnalysisResults {
|
||||
skeleton,
|
||||
const_paths: z.const_paths,
|
||||
const_vals: Arc::new(z.const_vals),
|
||||
capture_paths: z.capture_paths,
|
||||
assertion: a.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk(&mut self, mut a: &Assertion) -> Skeleton {
|
||||
while let Some(fields) = a.value().as_simple_record("Capture", Some(1)) {
|
||||
self.capture_paths.push(self.path.clone());
|
||||
a = &fields[0];
|
||||
}
|
||||
|
||||
if a.value().is_simple_record("Discard", Some(0)) {
|
||||
return Skeleton::Blank;
|
||||
} else {
|
||||
match class_of(a) {
|
||||
Some(cls) => {
|
||||
let arity = cls.arity();
|
||||
Skeleton::Guarded(cls,
|
||||
(0..arity).map(|i| {
|
||||
self.path.push(i);
|
||||
let s = self.walk(step(a, i));
|
||||
self.path.pop();
|
||||
s
|
||||
}).collect())
|
||||
}
|
||||
None => {
|
||||
self.const_paths.push(self.path.clone());
|
||||
self.const_vals.push(a.clone());
|
||||
Skeleton::Blank
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate_assertion(a: &Assertion, cs: Captures) -> CachedAssertion {
|
||||
let mut capture_paths = Vec::new();
|
||||
let mut path = Vec::new();
|
||||
let mut vs: Vec<Assertion> = (*cs).clone();
|
||||
vs.reverse();
|
||||
let instantiated = instantiate_assertion_walk(&mut capture_paths, &mut path, &mut vs, a);
|
||||
CachedAssertion::VisibilityRestricted(capture_paths, instantiated)
|
||||
}
|
||||
|
||||
fn instantiate_assertion_walk(capture_paths: &mut Paths,
|
||||
path: &mut Path,
|
||||
vs: &mut Vec<Assertion>,
|
||||
a: &Assertion) -> Assertion {
|
||||
if let Some(fields) = a.value().as_simple_record("Capture", Some(1)) {
|
||||
capture_paths.push(path.clone());
|
||||
let v = vs.pop().unwrap();
|
||||
instantiate_assertion_walk(capture_paths, path, vs, &fields[0]);
|
||||
return v;
|
||||
}
|
||||
|
||||
if a.value().is_simple_record("Discard", Some(0)) {
|
||||
return Value::Domain(Syndicate::new_placeholder()).wrap();
|
||||
} else {
|
||||
let f = |(i, aa)| {
|
||||
path.push(i);
|
||||
let vv = instantiate_assertion_walk(capture_paths,
|
||||
path,
|
||||
vs,
|
||||
aa);
|
||||
path.pop();
|
||||
vv
|
||||
};
|
||||
match class_of(a) {
|
||||
Some(Guard::Seq(_)) =>
|
||||
Value::from(Vec::from_iter(a.value().as_sequence().unwrap()
|
||||
.iter().enumerate().map(f)))
|
||||
.wrap(),
|
||||
Some(Guard::Rec(l, _)) =>
|
||||
Value::record(l, a.value().as_record().unwrap().1
|
||||
.iter().enumerate().map(f).collect())
|
||||
.wrap(),
|
||||
None =>
|
||||
a.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue