Skip to content

Commit

Permalink
Merge pull request #11 from lqd/unleash-the-treefrog
Browse files Browse the repository at this point in the history
Unleash the treefrog
  • Loading branch information
nikomatsakis committed Dec 5, 2018
2 parents 4d1e089 + 093c25a commit 58a7cb3
Show file tree
Hide file tree
Showing 7 changed files with 523 additions and 89 deletions.
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
language: rust
before_script:
- rustup component add rustfmt-preview
rust:
- beta
- nightly
matrix:
- fast_finish: true
- allow_failures:
- nightly
script:
- cargo build
- cargo fmt --all -- --check
- cargo test --all
39 changes: 17 additions & 22 deletions src/bin/borrow_check.rs → examples/borrow_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ type Borrow = u32;
type Point = u32;

fn main() {

let subset = {

// Create a new iteration context, ...
let mut iteration1 = Iteration::new();

Expand All @@ -34,37 +32,36 @@ fn main() {

// .. and then start iterating rules!
while iteration1.changed() {

// remap fields to re-index by keys.
subset_r1p.from_map(&subset, |&(r1,r2,p)| ((r1,p),r2));
subset_r2p.from_map(&subset, |&(r1,r2,p)| ((r2,p),r1));
subset_p.from_map(&subset, |&(r1,r2,p)| (p,(r1,r2)));
subset_r1p.from_map(&subset, |&(r1, r2, p)| ((r1, p), r2));
subset_r2p.from_map(&subset, |&(r1, r2, p)| ((r2, p), r1));
subset_p.from_map(&subset, |&(r1, r2, p)| (p, (r1, r2)));

// R0: subset(R1, R2, P) :- outlives(R1, R2, P).
// Already loaded; outlives is static.

// R1: subset(R1, R3, P) :-
// subset(R1, R2, P),
// subset(R2, R3, P).
subset.from_join(&subset_r2p, &subset_r1p, |&(_r2,p),&r1,&r3| (r1,r3,p));
subset.from_join(&subset_r2p, &subset_r1p, |&(_r2, p), &r1, &r3| (r1, r3, p));

// R2: subset(R1, R2, Q) :-
// subset(R1, R2, P),
// cfg_edge(P, Q),
// region_live_at(R1, Q),
// region_live_at(R2, Q).

subset_1.from_join(&subset_p, &cfg_edge_p, |&_p, &(r1,r2), &q| ((r1,q),r2));
subset_2.from_join(&subset_1, &region_live_at, |&(r1,q),&r2,&()| ((r2,q),r1));
subset.from_join(&subset_2, &region_live_at, |&(r2,q),&r1,&()| (r1,r2,q));

subset_1.from_join(&subset_p, &cfg_edge_p, |&_p, &(r1, r2), &q| ((r1, q), r2));
subset_2.from_join(&subset_1, &region_live_at, |&(r1, q), &r2, &()| {
((r2, q), r1)
});
subset.from_join(&subset_2, &region_live_at, |&(r2, q), &r1, &()| (r1, r2, q));
}

subset_r1p.complete()
};

let requires = {

// Create a new iteration context, ...
let mut iteration2 = Iteration::new();

Expand All @@ -87,9 +84,8 @@ fn main() {

// .. and then start iterating rules!
while iteration2.changed() {

requires_rp.from_map(&requires, |&(r,b,p)| ((r,p),b));
requires_bp.from_map(&requires, |&(r,b,p)| ((b,p),r));
requires_rp.from_map(&requires, |&(r, b, p)| ((r, p), b));
requires_bp.from_map(&requires, |&(r, b, p)| ((b, p), r));

// requires(R, B, P) :- borrow_region(R, B, P).
// Already loaded; borrow_region is static.
Expand All @@ -105,16 +101,15 @@ fn main() {
// cfg_edge(P, Q),
// (region_live_at(R, Q); universal_region(R)).

requires_1.from_antijoin(&requires_bp, &killed, |&(b,p),&r| (p,(b,r)));
requires_2.from_join(&requires_1, &cfg_edge_p, |&_p, &(b,r), &q| ((r,q),b));
requires.from_join(&requires_2, &region_live_at, |&(r,q),&b,&()| (r,b,q));
requires_1.from_antijoin(&requires_bp, &killed, |&(b, p), &r| (p, (b, r)));
requires_2.from_join(&requires_1, &cfg_edge_p, |&_p, &(b, r), &q| ((r, q), b));
requires.from_join(&requires_2, &region_live_at, |&(r, q), &b, &()| (r, b, q));
}

requires.complete()
};

// borrow_live_at(B, P) :- requires(R, B, P), region_live_at(R, P)

// borrow_live_at(B, P) :- requires(R, B, P), universal_region(R).
// borrow_live_at(B, P) :- requires(R, B, P), region_live_at(R, P)

}
// borrow_live_at(B, P) :- requires(R, B, P), universal_region(R).
}
26 changes: 16 additions & 10 deletions src/bin/graspan1.rs → examples/graspan1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ extern crate datafrog;
use datafrog::Iteration;

fn main() {

let timer = ::std::time::Instant::now();

// Make space for input data.
let mut nodes = Vec::new();
let mut edges = Vec::new();

// Read input data from a handy file.
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::io::{BufRead, BufReader};

let filename = std::env::args().nth(1).unwrap();
let file = BufReader::new(File::open(filename).unwrap());
Expand All @@ -23,9 +22,13 @@ fn main() {
let dst: u32 = elts.next().unwrap().parse().expect("malformed dst");
let typ: &str = elts.next().unwrap();
match typ {
"n" => { nodes.push((dst, src)); },
"e" => { edges.push((src, dst)); },
unk => { panic!("unknown type: {}", unk)},
"n" => {
nodes.push((dst, src));
}
"e" => {
edges.push((src, dst));
}
unk => panic!("unknown type: {}", unk),
}
}
}
Expand All @@ -36,8 +39,8 @@ fn main() {
let mut iteration = Iteration::new();

// .. some variables, ..
let variable1 = iteration.variable::<(u32,u32)>("nodes");
let variable2 = iteration.variable::<(u32,u32)>("edges");
let variable1 = iteration.variable::<(u32, u32)>("nodes");
let variable2 = iteration.variable::<(u32, u32)>("edges");

// .. load them with some initial values, ..
variable1.insert(nodes.into());
Expand All @@ -46,11 +49,14 @@ fn main() {
// .. and then start iterating rules!
while iteration.changed() {
// N(a,c) <- N(a,b), E(b,c)
variable1.from_join(&variable1, &variable2, |_b, &a, &c| (c,a));
variable1.from_join(&variable1, &variable2, |_b, &a, &c| (c, a));
}

let reachable = variable1.complete();

println!("{:?}\tComputation complete (nodes_final: {})", timer.elapsed(), reachable.len());

println!(
"{:?}\tComputation complete (nodes_final: {})",
timer.elapsed(),
reachable.len()
);
}
45 changes: 25 additions & 20 deletions src/join.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
//! Join functionality.

use super::{Variable, Relation};
use super::{Relation, Variable};

pub fn join_into<Key: Ord, Val1: Ord, Val2: Ord, Result: Ord>(
input1: &Variable<(Key, Val1)>,
input2: &Variable<(Key, Val2)>,
output: &Variable<Result>,
mut logic: impl FnMut(&Key, &Val1, &Val2)->Result) {

mut logic: impl FnMut(&Key, &Val1, &Val2) -> Result,
) {
let mut results = Vec::new();

let recent1 = input1.recent.borrow();
let recent2 = input2.recent.borrow();

{ // scoped to let `closure` drop borrow of `results`.
{
// scoped to let `closure` drop borrow of `results`.

let mut closure = |k: &Key, v1: &Val1, v2: &Val2| results.push(logic(k,v1,v2));
let mut closure = |k: &Key, v1: &Val1, v2: &Val2| results.push(logic(k, v1, v2));

for batch2 in input2.stable.borrow().iter() {
join_helper(&recent1, &batch2, &mut closure);
Expand All @@ -36,40 +37,44 @@ pub fn antijoin_into<Key: Ord, Val: Ord, Result: Ord>(
input1: &Variable<(Key, Val)>,
input2: &Relation<Key>,
output: &Variable<Result>,
mut logic: impl FnMut(&Key, &Val)->Result) {

mut logic: impl FnMut(&Key, &Val) -> Result,
) {
let mut tuples2 = &input2[..];

let results = input1.recent.borrow().iter().filter(|(ref key, _)| {
tuples2 = gallop(tuples2, |k| k < key);
tuples2.first() != Some(key)
}).map(|(ref key, ref val)| logic(key, val)).collect::<Vec<_>>();
let results = input1
.recent
.borrow()
.iter()
.filter(|(ref key, _)| {
tuples2 = gallop(tuples2, |k| k < key);
tuples2.first() != Some(key)
})
.map(|(ref key, ref val)| logic(key, val))
.collect::<Vec<_>>();

output.insert(Relation::from_vec(results));
}

fn join_helper<K: Ord, V1, V2>(
mut slice1: &[(K,V1)],
mut slice2: &[(K,V2)],
mut result: impl FnMut(&K,&V1,&V2)) {

mut slice1: &[(K, V1)],
mut slice2: &[(K, V2)],
mut result: impl FnMut(&K, &V1, &V2),
) {
while !slice1.is_empty() && !slice2.is_empty() {

use std::cmp::Ordering;

// If the keys match produce tuples, else advance the smaller key until they might.
match slice1[0].0.cmp(&slice2[0].0) {
Ordering::Less => {
slice1 = gallop(slice1, |x| x.0 < slice2[0].0);
},
}
Ordering::Equal => {

// Determine the number of matching keys in each slice.
let count1 = slice1.iter().take_while(|x| x.0 == slice1[0].0).count();
let count2 = slice2.iter().take_while(|x| x.0 == slice2[0].0).count();

// Produce results from the cross-product of matches.
for index1 in 0 .. count1 {
for index1 in 0..count1 {
for s2 in slice2[..count2].iter() {
result(&slice1[0].0, &slice1[index1].1, &s2.1);
}
Expand All @@ -86,7 +91,7 @@ fn join_helper<K: Ord, V1, V2>(
}
}

pub fn gallop<T>(mut slice: &[T], mut cmp: impl FnMut(&T)->bool) -> &[T] {
pub fn gallop<T>(mut slice: &[T], mut cmp: impl FnMut(&T) -> bool) -> &[T] {
// if empty slice, or already >= element, return
if !slice.is_empty() && cmp(&slice[0]) {
let mut step = 1;
Expand Down
Loading

0 comments on commit 58a7cb3

Please sign in to comment.