<commit_before>use std::cmp::Reverse;
use std::collections::HashMap;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use regex::Regex;

use common::Solution;
use std::collections::HashSet;
use std::collections::BinaryHeap;

fn append_edge(target: &mut HashMap<char, Vec<char>>, source: char, dest: char) {
    target.entry(source).or_insert(Vec::new()).push(dest);
}

#[derive(Default, Debug)]
pub struct Day07 {
    forward: HashMap<char, Vec<char>>,
    backward: HashMap<char, Vec<char>>,
}

impl Day07 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_edges(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let regex = Regex::new(r"Step (\w) must be finished before step (\w) can begin").unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = regex.captures(&line).unwrap();
            let a = groups[1].chars().next().unwrap();
            let b = groups[2].chars().next().unwrap();

            append_edge(&mut self.forward, a, b);
            append_edge(&mut self.backward, b, a);
        }
    }
}

impl Solution for Day07 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_edges(input);

        let mut result = String::new();
        let mut finished = HashSet::new();

        let mut starting_points: BinaryHeap<Reverse<char>> = self.forward.keys().filter(|&x| !self.backward.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        while let Some(Reverse(c)) = starting_points.pop() {
            result.push(c);
            finished.insert(c);

            if let Some(dependents) = self.forward.get(&c) {
                for d in dependents {
                    if self.backward.get(d).unwrap().iter().all(|x| finished.contains(x)) {
                        starting_points.push(Reverse(*d));
                    }
                }
            }
        }

        result
    }

    fn part2(&mut self, input: &mut Read) -> String {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day07::Day07;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/07.txt");

    #[test]
    pub fn sample_part1() {
        let mut instance = Day07::new();
        assert_eq!("CABDFE", instance.part1(&mut SAMPLE_INPUT));
    }
}
<commit_msg>Implement part 2.<commit_after>use std::cmp::Ordering;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use regex::Regex;

use common::Solution;

fn append_edge(target: &mut HashMap<char, Vec<char>>, source: char, dest: char) {
    target.entry(source).or_insert(Vec::new()).push(dest);
}

#[derive(Debug, Eq, PartialEq)]
struct Worker {
    time: usize,
    work: char,
}

impl Ord for Worker {
    fn cmp(&self, other: &Self) -> Ordering {
        other.time.cmp(&self.time)
            .then(other.work.cmp(&self.work))
    }
}

impl PartialOrd for Worker {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Default, Debug)]
pub struct Day07 {
    forward: HashMap<char, Vec<char>>,
    backward: HashMap<char, Vec<char>>,
}

impl Day07 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_edges(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let regex = Regex::new(r"Step (\w) must be finished before step (\w) can begin").unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = regex.captures(&line).unwrap();
            let a = groups[1].chars().next().unwrap();
            let b = groups[2].chars().next().unwrap();

            append_edge(&mut self.forward, a, b);
            append_edge(&mut self.backward, b, a);
        }
    }

    fn part2_parametrized(&mut self, input: &mut Read, base_time: usize, max_workers: usize) -> usize {
        self.read_edges(input);
        let mut starting_points: BinaryHeap<Reverse<char>> = self.forward.keys()
            .filter(|&x| !self.backward.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        let mut workers: BinaryHeap<Worker> = BinaryHeap::new();
        let mut finished = HashSet::new();
        let mut time = 0;

        while !starting_points.is_empty() || !workers.is_empty() {
            while workers.len() < max_workers && !starting_points.is_empty() {
                let Reverse(to_start) = starting_points.pop().unwrap();
                workers.push(Worker {
                    time: time + base_time + ((to_start as u8) - b'A' + 1) as usize,
                    work: to_start,
                });
            }

            time = workers.peek().unwrap().time;

            while let Some(worker) = workers.pop() {
                if worker.time == time {
                    let c = worker.work;
                    finished.insert(c);

                    if let Some(dependents) = self.forward.get(&c) {
                        for d in dependents {
                            if self.backward.get(d).unwrap().iter().all(|x| finished.contains(x)) {
                                starting_points.push(Reverse(*d));
                            }
                        }
                    }
                } else {
                    workers.push(worker);
                    break;
                }
            }
        }

        time
    }
}

impl Solution for Day07 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_edges(input);

        let mut result = String::new();
        let mut finished = HashSet::new();

        let mut starting_points: BinaryHeap<_> = self.forward.keys().filter(|&x| !self.backward.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        while let Some(Reverse(c)) = starting_points.pop() {
            result.push(c);
            finished.insert(c);

            if let Some(dependents) = self.forward.get(&c) {
                for d in dependents {
                    if self.backward.get(d).unwrap().iter().all(|x| finished.contains(x)) {
                        starting_points.push(Reverse(*d));
                    }
                }
            }
        }

        result
    }

    fn part2(&mut self, input: &mut Read) -> String {
        format!("{}", self.part2_parametrized(input, 60, 5))
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day07::Day07;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/07.txt");

    #[test]
    pub fn sample_part1() {
        let mut instance = Day07::new();
        assert_eq!("CABDFE", instance.part1(&mut SAMPLE_INPUT));
    }

    #[test]
    pub fn sample_part2() {
        let mut instance = Day07::new();
        assert_eq!(15, instance.part2_parametrized(&mut SAMPLE_INPUT, 0, 2));
    }
}
<|endoftext|>


<commit_before>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use crate::Solution;

fn seat_id(boarding_pass: &str) -> u32 {
    boarding_pass
        .chars()
        .fold(0, |b, c| (b << 1) | ((c == 'B' || c == 'R') as u32))
}

fn seat_iter<'a>(input: &'a mut dyn Read) -> impl Iterator<Item = u32> + 'a {
    BufReader::new(input).lines().map(|s| seat_id(&s.unwrap()))
}

#[derive(Default)]
pub struct Day05;

impl Solution for Day05 {
    fn part1(&mut self, input: &mut dyn Read) -> String {
        seat_iter(input).max().unwrap().to_string()
    }

    fn part2(&mut self, input: &mut dyn Read) -> String {
        let mut taken = [false; 0x3ff];

        for seat_id in seat_iter(input) {
            taken[seat_id as usize] = true;
        }

        let pattern = [true, false, true];

        for (i, window) in taken.windows(3).enumerate() {
            if window == pattern {
                return (i + 1).to_string();
            }
        }

        panic!("No seat found!");
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_seat_id() {
        assert_eq!(567, seat_id("BFFFBBFRRR"));
        assert_eq!(119, seat_id("FFFBBBFRRR"));
        assert_eq!(820, seat_id("BBFFBBFRLL"));
    }
}
<commit_msg>Off-by-one error<commit_after>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use crate::Solution;

fn seat_id(boarding_pass: &str) -> u32 {
    boarding_pass
        .chars()
        .fold(0, |b, c| (b << 1) | ((c == 'B' || c == 'R') as u32))
}

fn seat_iter<'a>(input: &'a mut dyn Read) -> impl Iterator<Item = u32> + 'a {
    BufReader::new(input).lines().map(|s| seat_id(&s.unwrap()))
}

#[derive(Default)]
pub struct Day05;

impl Solution for Day05 {
    fn part1(&mut self, input: &mut dyn Read) -> String {
        seat_iter(input).max().unwrap().to_string()
    }

    fn part2(&mut self, input: &mut dyn Read) -> String {
        let mut taken = [false; 0x400];

        for seat_id in seat_iter(input) {
            taken[seat_id as usize] = true;
        }

        let pattern = [true, false, true];

        for (i, window) in taken.windows(3).enumerate() {
            if window == pattern {
                return (i + 1).to_string();
            }
        }

        panic!("No seat found!");
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_seat_id() {
        assert_eq!(567, seat_id("BFFFBBFRRR"));
        assert_eq!(119, seat_id("FFFBBBFRRR"));
        assert_eq!(820, seat_id("BBFFBBFRLL"));
    }
}
<|endoftext|>


<commit_before>extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::fs::File;
use std::slice;
use std::mem;

use dataflow_join::graph::{GraphTrait, GraphVector};

static USAGE: &'static str = "
Usage: digest <source> <target>
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    println!("digest will overwrite <target>.targets and <target>.offsets, so careful");
    println!("at least, it will once you edit the code to uncomment the line.");
    let source = args.get_str("<source>");
    let _target = args.get_str("<target>");
    let mut graph = livejournal(&source);
    organize_graph(&mut graph);
    _digest_graph_vector(&_extract_fragment(graph.iter().map(|x| *x), 0, 1), _target); // will overwrite "prefix.offsets" and "prefix.targets"

}

// loads the livejournal file available at https://snap.stanford.edu/data/soc-LiveJournal1.html
fn livejournal(filename: &str) -> Vec<(u32, u32)> {
    let mut graph = Vec::new();
    let file = BufReader::new(File::open(filename).unwrap());
    for readline in file.lines() {
        let line = readline.ok().expect("read error");
        if !line.starts_with('#') {
            let elts: Vec<&str> = line[..].split(" ").collect();
            let src: u32 = elts[0].parse().ok().expect("malformed src");
            let dst: u32 = elts[1].parse().ok().expect("malformed dst");
            if src < dst { graph.push((src, dst)) }
            if src > dst { graph.push((dst, src)) }
        }
    }

    println!("graph data loaded; {:?} edges", graph.len());
    return graph;
}

fn organize_graph(graph: &mut Vec<(u32, u32)>) {

    for index in (0..graph.len()) {
        if graph[index].1 < graph[index].0 {
            graph[index] = (graph[index].1, graph[index].0);
        }
    }

    graph.sort();
    println!("graph data sorted; {:?} edges", graph.len());

    graph.dedup();
    println!("graph data uniqed; {:?} edges", graph.len());

    // speeds things up a bit by tweaking edge directions.
    // loses the src < dst property, which can be helpful.
    redirect(graph);
    graph.sort();
    println!("graph data dirctd; {:?} edges", graph.len());
}

fn redirect(edges: &mut Vec<(u32, u32)>) {
    let mut degrees = Vec::new();
    for &(src, dst) in edges.iter() {
        while src as usize >= degrees.len() { degrees.push(0); }
        while dst as usize >= degrees.len() { degrees.push(0); }
        degrees[src as usize] += 1;
        degrees[dst as usize] += 1;
    }

    for index in (0..edges.len()) {
        if degrees[edges[index].0 as usize] > degrees[edges[index].1 as usize] {
            edges[index] = (edges[index].1, edges[index].0);
        }
    }
}

fn _extract_fragment<I: Iterator<Item=(u32, u32)>>(graph: I, index: u64, parts: u64) -> GraphVector<u32> {
    let mut nodes = Vec::new();
    let mut edges = Vec::new();

    for (src, dst) in graph {
        if src as u64 % parts == index {
            while src + 1 >= nodes.len() as u32 { nodes.push(0); }
            while dst + 1 >= nodes.len() as u32 { nodes.push(0); } // allows unsafe access to nodes

            nodes[src as usize + 1] += 1;
            edges.push(dst);
        }
    }

    for index in (1..nodes.len()) {
        nodes[index] += nodes[index - 1];
    }

    return GraphVector { nodes: nodes, edges: edges };
}

fn _digest_graph_vector<E: Ord+Copy>(graph: &GraphVector<E>, output_prefix: &str) {
    let mut edge_writer = BufWriter::new(File::create(format!("{}.targets", output_prefix)).unwrap());
    let mut node_writer = BufWriter::new(File::create(format!("{}.offsets", output_prefix)).unwrap());
    node_writer.write_all(unsafe { _typed_as_byte_slice(&graph.nodes[..]) }).unwrap();

    let mut slice = unsafe { _typed_as_byte_slice(&graph.edges[..]) };
    while slice.len() > 0 {
        let to_write = if slice.len() < 1000000 { slice.len() } else { 1000000 };
        edge_writer.write_all(&slice[..to_write]).unwrap();
        println!("wrote some; remaining: {}", slice.len());
        slice = &slice[to_write..];
    }
}

unsafe fn _typed_as_byte_slice<T>(slice: &[T]) -> &[u8] {
    slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>())
}
<commit_msg>updated digest to not adjust the graph<commit_after>extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::fs::File;
use std::slice;
use std::mem;

use dataflow_join::graph::{GraphTrait, GraphVector};

static USAGE: &'static str = "
Usage: digest <source> <target>
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    println!("digest will overwrite <target>.targets and <target>.offsets, so careful");
    println!("at least, it will once you edit the code to uncomment the line.");
    let source = args.get_str("<source>");
    let _target = args.get_str("<target>");
    let mut graph = livejournal(&source);
    // organize_graph(&mut graph);
    _digest_graph_vector(&_extract_fragment(graph.iter().map(|x| *x), 0, 1), _target); // will overwrite "prefix.offsets" and "prefix.targets"

}

// loads the livejournal file available at https://snap.stanford.edu/data/soc-LiveJournal1.html
fn livejournal(filename: &str) -> Vec<(u32, u32)> {
    let mut graph = Vec::new();
    let file = BufReader::new(File::open(filename).unwrap());
    for readline in file.lines() {
        let line = readline.ok().expect("read error");
        if !line.starts_with('#') {
            let elts: Vec<&str> = line[..].split(",").collect();
            let src: u32 = elts[0].parse().ok().expect("malformed src");
            let dst: u32 = elts[1].parse().ok().expect("malformed dst");
            graph.push((src, dst))
            // if src < dst { graph.push((src, dst)) }
            // if src > dst { graph.push((dst, src)) }
        }
    }

    println!("graph data loaded; {:?} edges", graph.len());
    return graph;
}

fn organize_graph(graph: &mut Vec<(u32, u32)>) {

    for index in (0..graph.len()) {
        if graph[index].1 < graph[index].0 {
            graph[index] = (graph[index].1, graph[index].0);
        }
    }

    graph.sort();
    println!("graph data sorted; {:?} edges", graph.len());

    graph.dedup();
    println!("graph data uniqed; {:?} edges", graph.len());

    // speeds things up a bit by tweaking edge directions.
    // loses the src < dst property, which can be helpful.
    redirect(graph);
    graph.sort();
    println!("graph data dirctd; {:?} edges", graph.len());
}

fn redirect(edges: &mut Vec<(u32, u32)>) {
    let mut degrees = Vec::new();
    for &(src, dst) in edges.iter() {
        while src as usize >= degrees.len() { degrees.push(0); }
        while dst as usize >= degrees.len() { degrees.push(0); }
        degrees[src as usize] += 1;
        degrees[dst as usize] += 1;
    }

    for index in (0..edges.len()) {
        if degrees[edges[index].0 as usize] > degrees[edges[index].1 as usize] {
            edges[index] = (edges[index].1, edges[index].0);
        }
    }
}

fn _extract_fragment<I: Iterator<Item=(u32, u32)>>(graph: I, index: u64, parts: u64) -> GraphVector<u32> {
    let mut nodes = Vec::new();
    let mut edges = Vec::new();

    for (src, dst) in graph {
        if src as u64 % parts == index {
            while src + 1 >= nodes.len() as u32 { nodes.push(0); }
            while dst + 1 >= nodes.len() as u32 { nodes.push(0); } // allows unsafe access to nodes

            nodes[src as usize + 1] += 1;
            edges.push(dst);
        }
    }

    for index in (1..nodes.len()) {
        nodes[index] += nodes[index - 1];
    }

    return GraphVector { nodes: nodes, edges: edges };
}

fn _digest_graph_vector<E: Ord+Copy>(graph: &GraphVector<E>, output_prefix: &str) {
    let mut edge_writer = BufWriter::new(File::create(format!("{}.targets", output_prefix)).unwrap());
    let mut node_writer = BufWriter::new(File::create(format!("{}.offsets", output_prefix)).unwrap());
    node_writer.write_all(unsafe { _typed_as_byte_slice(&graph.nodes[..]) }).unwrap();

    let mut slice = unsafe { _typed_as_byte_slice(&graph.edges[..]) };
    while slice.len() > 0 {
        let to_write = if slice.len() < 1000000 { slice.len() } else { 1000000 };
        edge_writer.write_all(&slice[..to_write]).unwrap();
        println!("wrote some; remaining: {}", slice.len());
        slice = &slice[to_write..];
    }
}

unsafe fn _typed_as_byte_slice<T>(slice: &[T]) -> &[u8] {
    slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>())
}
<|endoftext|>


<commit_before>//! Draw a dragon curve, more specifically a highway dragon.
//! (https://en.wikipedia.org/wiki/Dragon_curve)
//!
//! As can be seen in the above wikipedia article, the highway dragon can be
//! constructed by repeatedly folding a strip of paper and looking at the
//! directions of the folds/turns.
//!
//! Starting with a strip going left to right (l2r):
//!
//! start|--->---l2r--->---|end
//!
//! you might fold it like this:
//!
//! end|---<---r2l---<---\
//! start|->---l2r--->---/
//!
//! Getting a l2r strip, followed by a left turn, followed by a r2l strip.
//!
//! Folding a right to left strip:
//!
//! end|---<---r2l---<---|start
//!
//! In the same way:
//!
//! start|-->---l2r--->---\
//! end|----<---r2l---<---/
//!
//! Would give you a l2r, followed by a right turn, followed by a r2l strip.
//!
//! As you can see, the only difference between the two is the direction of
//! the turn in the middle.
//!
//! This folding of paper is simulated by recursively calling the dragon(..)
//! function, passing the direction of the turn for this fold as an angle
//! (+90 for a right turn, -90 for a left turn).

use turtle::Color;
use turtle::{Drawing, Turtle};

fn main() {
    let mut drawing = Drawing::new();
    let mut turtle = drawing.add_turtle();

    drawing.set_background_color("#112244");

    turtle.pen_up();
    turtle.backward(160.0);
    turtle.right(90.);
    turtle.forward(110.);
    turtle.pen_down();
    turtle.set_speed("faster");

    dragon(&mut turtle, -90., 11, 0., 255.);

    turtle.hide();
}

/// Draw the dragon curve by simulating folding a strip of paper
///
/// `fold_direction`: The direction of the fold, +90 for a right, -90 for a
/// left turn.
/// `num_folds`: The number of times to fold the 'strip of paper'.
/// `color_start`/`color_end`: The color at the start/end of this subsection
/// of the curve as a number 0-255.
fn dragon(turtle: &mut Turtle, fold_direction: f64, num_folds: usize, color_start: f64, color_end: f64) {
    let color_mid = (color_start + color_end) * 0.5;
    if num_folds == 0 {
        // mapping a color number 0-255 to an rgb gradient.
        turtle.set_pen_color(Color {
            red: ((color_mid - 128.).abs() * 2.).floor(),
            green: color_mid,
            blue: 160.,
            alpha: 1.,
        });
        return turtle.forward(10.);
    }

    // draw a left to right strip (which has a left turn in the middle)
    dragon(turtle, -90., num_folds - 1, color_start, color_mid);
    turtle.right(fold_direction);
    // draw a right to left strip (which has a right turn in the middle)
    dragon(turtle, 90., num_folds - 1, color_mid, color_end);
}
<commit_msg>Fix dragon curve name<commit_after>//! Draw a dragon curve, more specifically a Heighway dragon.
//! (https://en.wikipedia.org/wiki/Dragon_curve)
//!
//! As can be seen in the above Wikipedia article, the Heighway dragon can be
//! constructed by repeatedly folding a strip of paper and looking at the
//! directions of the folds/turns.
//!
//! Starting with a strip going left to right (l2r):
//!
//! start|--->---l2r--->---|end
//!
//! you might fold it like this:
//!
//! end|---<---r2l---<---\
//! start|->---l2r--->---/
//!
//! Getting a l2r strip, followed by a left turn, followed by a r2l strip.
//!
//! Folding a right to left strip:
//!
//! end|---<---r2l---<---|start
//!
//! In the same way:
//!
//! start|-->---l2r--->---\
//! end|----<---r2l---<---/
//!
//! Would give you a l2r, followed by a right turn, followed by a r2l strip.
//!
//! As you can see, the only difference between the two is the direction of
//! the turn in the middle.
//!
//! This folding of paper is simulated by recursively calling the dragon(..)
//! function, passing the direction of the turn for this fold as an angle
//! (+90 for a right turn, -90 for a left turn).

use turtle::Color;
use turtle::{Drawing, Turtle};

fn main() {
    let mut drawing = Drawing::new();
    let mut turtle = drawing.add_turtle();

    drawing.set_background_color("#112244");

    turtle.pen_up();
    turtle.backward(160.0);
    turtle.right(90.);
    turtle.forward(110.);
    turtle.pen_down();
    turtle.set_speed("faster");

    dragon(&mut turtle, -90., 11, 0., 255.);

    turtle.hide();
}

/// Draw the dragon curve by simulating folding a strip of paper
///
/// `fold_direction`: The direction of the fold, +90 for a right, -90 for a
/// left turn.
/// `num_folds`: The number of times to fold the 'strip of paper'.
/// `color_start`/`color_end`: The color at the start/end of this subsection
/// of the curve as a number 0-255.
fn dragon(turtle: &mut Turtle, fold_direction: f64, num_folds: usize, color_start: f64, color_end: f64) {
    let color_mid = (color_start + color_end) * 0.5;
    if num_folds == 0 {
        // mapping a color number 0-255 to an rgb gradient.
        turtle.set_pen_color(Color {
            red: ((color_mid - 128.).abs() * 2.).floor(),
            green: color_mid,
            blue: 160.,
            alpha: 1.,
        });
        return turtle.forward(10.);
    }

    // draw a left to right strip (which has a left turn in the middle)
    dragon(turtle, -90., num_folds - 1, color_start, color_mid);
    turtle.right(fold_direction);
    // draw a right to left strip (which has a right turn in the middle)
    dragon(turtle, 90., num_folds - 1, color_mid, color_end);
}
<|endoftext|>


<commit_before>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    // Intrepreter initialization
    let program = parity_wasm::DefaultProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Program instance to load");

    let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");

    // Extracts call arguments from command-line arguments
    let execution_params = {
        // Export section has an entry with a func_name with an index inside a module
        let export_section = module.export_section().expect("No export section found");
        // It's a section where function to be found in
        let function_section = module.function_section().expect("No function section found");
        // Type section stores function types
        let type_section = module.type_section().expect("No type section found");

        // A found export entry by the name
        let found_entry = export_section.entries().iter()
            .find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));

        // Function index with imported functions
        let function_index: usize = match found_entry.internal() {
            &Internal::Function(index) => index as usize,
            _ => panic!("Founded export is not a function"),
        };
        // Counts import section entries
        let import_section_len: usize = match module.import_section() {
            Some(import) =>
                import.entries().iter().filter(|entry| match entry.external() {
                    &External::Function(_) => true,
                    _ => false,
                    }).count(),
            None => 0,
        };

        // Calculates a function index within function section
        let function_index_in_section = function_index - import_section_len;

        // Type a type ref (an index inside of types section of module)
        let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
        let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
            &Type::Function(ref func_type) => func_type,
        };

        // Parses arguments and constructs runtime values in correspondence of their types
        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    // Intialize deserialized module
    let module = program.add_module("main", module, None).expect("Failed to initialize module");

    println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}
<commit_msg>fix comments<commit_after>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    // Intrepreter initialization.
    // parity_wasm::ProgramInstance can be parameterized with a custom User error which could be returned from imported functions
    // parity_wasm::DefaultProgramInstance parametrize ProgramInstance with a pre-defined "DummyUserError"
    let program = parity_wasm::DefaultProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Program instance to load");

    let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");

    // Extracts call arguments from command-line arguments
    let execution_params = {
        // Export section has an entry with a func_name with an index inside a module
        let export_section = module.export_section().expect("No export section found");
        // It's a section with function declarations (which are references to the type section entries)
        let function_section = module.function_section().expect("No function section found");
        // Type section stores function types which are referenced by function_section entries
        let type_section = module.type_section().expect("No type section found");

        // A given function name used to find export section entry which contains
        // an `internal` field which points to the index in the function index space
        let found_entry = export_section.entries().iter()
            .find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));

        // Function index in the function index space (internally-defined + imported)
        let function_index: usize = match found_entry.internal() {
            &Internal::Function(index) => index as usize,
            _ => panic!("Founded export is not a function"),
        };
        // We need to count import section entries to substract it from
        let import_section_len: usize = match module.import_section() {
            Some(import) =>
                import.entries().iter().filter(|entry| match entry.external() {
                    &External::Function(_) => true,
                    _ => false,
                    }).count(),
            None => 0,
        };

        // Calculates a function index within module's function section
        let function_index_in_section = function_index - import_section_len;

        // Getting a type reference from a function section entry
        let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;

        // Use the reference to get an actual function type
        let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
            &Type::Function(ref func_type) => func_type,
        };

        // Parses arguments and constructs runtime values in correspondence of their types
        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    // Intialize deserialized module.
    let module = program.add_module("main", module, None).expect("Failed to initialize module");

    println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}
<|endoftext|>


<commit_before>use engine::World;
use engine::log;
use util::units::Direction;

/// The entire game state.
pub struct Game {
    pub world: World,
}

pub enum Command {
    Walk(Direction),
}

impl Game {

    /// Creates a new game.
    pub fn new() -> Game {
        Game {
            world: World::new(),
        }
    }

    pub fn do_command(&mut self, cmd: Command) {
        match cmd {
            Command::Walk(d) => {
                self.world.walk(d);
            }
        }
    }

    pub fn step(&mut self) {

    }

}
<commit_msg>Remove an unused import to prevent a warning<commit_after>use engine::World;

use util::units::Direction;

/// The entire game state.
pub struct Game {
    pub world: World,
}

pub enum Command {
    Walk(Direction),
}

impl Game {

    /// Creates a new game.
    pub fn new() -> Game {
        Game {
            world: World::new(),
        }
    }

    pub fn do_command(&mut self, cmd: Command) {
        match cmd {
            Command::Walk(d) => {
                self.world.walk(d);
            }
        }
    }

    pub fn step(&mut self) {

    }

}
<|endoftext|>


<commit_before>use services::{ AdapterId, Service, ServiceId, ChannelKind, Channel, Getter, Setter, TagId };
use util::{ Exactly, Id };
use values::Duration;

use std::cmp;
use std::hash::Hash;
use std::collections::HashSet;

use serde::ser::Serializer;
use serde::de::Deserializer;

fn merge<T>(mut a: HashSet<T>, b: Vec<T>) -> HashSet<T> where T: Hash + Eq {
    for x in b {
        a.insert(x);
    }
    a
}

pub trait SelectedBy<T> {
    fn matches(&self, &T) -> bool;
}

/// A trait used to let ServiceSelector work on complex data structures
/// that are not necessarily exactly Selector.
pub trait ServiceLike {
    fn id(&self) -> &Id<ServiceId>;
    fn tags(&self) -> &HashSet<Id<TagId>>;
    fn adapter(&self) -> &Id<AdapterId>;
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool;
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool;
}

impl ServiceLike for Service {
    fn id(&self) -> &Id<ServiceId> {
        &self.id
    }
    fn tags(&self) -> &HashSet<Id<TagId>> {
        &self.tags
    }
    fn adapter(&self) -> &Id<AdapterId> {
        &self.adapter
    }
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool {
        for chan in self.getters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool {
        for chan in self.setters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }

}

/// A selector for one or more services.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = ServiceSelector::new()
///   .with_tags(vec![Id::<TagId>::new("entrance")])
///   .with_getters(vec![GetterSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ServiceSelector {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<ServiceId>>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    /// Restrict results to services that have all the getters in `getters`.
    #[serde(default)]
    pub getters: Vec<GetterSelector>,

    /// Restrict results to services that have all the setters in `setters`.
    #[serde(default)]
    pub setters: Vec<SetterSelector>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl ServiceSelector {
    /// Create a new selector that accepts all services.
    pub fn new() -> Self {
        Self::default()
    }

    /// Selector for a service with a specific id.
    pub fn with_id(self, id: Id<ServiceId>) -> Self {
        ServiceSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        ServiceSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to services that have all the getters in `getters`.
    pub fn with_getters(mut self, mut getters: Vec<GetterSelector>) -> Self {
        ServiceSelector {
            getters: {self.getters.append(&mut getters); self.getters},
            .. self
        }
    }

    /// Restrict results to services that have all the setters in `setters`.
    pub fn with_setters(mut self, mut setters: Vec<SetterSelector>) -> Self {
        ServiceSelector {
            setters: {self.setters.append(&mut setters); self.setters},
            .. self
        }
    }

    /// Restrict results to services that are accepted by two selector.
    pub fn and(mut self, mut other: ServiceSelector) -> Self {
        ServiceSelector {
            id: self.id.and(other.id),
            tags: self.tags.union(&other.tags).cloned().collect(),
            getters: {self.getters.append(&mut other.getters); self.getters},
            setters: {self.setters.append(&mut other.setters); self.setters},
            private: (),
        }
    }

    pub fn matches<T>(&self, service: &T) -> bool
        where T: ServiceLike
    {
        if !self.id.matches(service.id()) {
            return false;
        }
        if !has_selected_tags(&self.tags, service.tags()) {
            return false;
        }
        // If any of the getter selectors doesn't find a getter,
        // we don't match.
        let getters_fail = self.getters.iter().find(|selector| {
            !service.has_getters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if getters_fail {
            return false;
        }
        // If any of the setter selectors doesn't find a setter,
        // we don't match.
        let setters_fail = self.setters.iter().find(|selector| {
            !service.has_setters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if setters_fail {
            return false;
        }
        true
    }
}

impl SelectedBy<ServiceSelector> for Service {
    fn matches(&self, selector: &ServiceSelector) -> bool {
        selector.matches(self)
    }
}

/// A selector for one or more getter channels.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = GetterSelector::new()
///   .with_parent(Id::new("foxbox"))
///   .with_kind(ChannelKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GetterSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Getter>>,

    /// If `Eactly(id)`, return only channels that are children of
    /// service `id`.
    #[serde(default)]
    pub parent: Exactly<Id<ServiceId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

    /// If `Exatly(k)`, restrict results to channels that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl GetterSelector {
    /// Create a new selector that accepts all getter channels.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a channel with a specific id.
    pub fn with_id(self, id: Id<Getter>) -> Self {
        GetterSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific parent.
    pub fn with_parent(self, id: Id<ServiceId>) -> Self {
        GetterSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetterSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        GetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        GetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Getter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

/// A selector for one or more setter channels.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct SetterSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Setter>>,

    /// If `Exactly(id)`, return only channels that are immediate children
    /// of service `id`.
    #[serde(default)]
    pub parent: Exactly<Id<ServiceId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

    /// If `Exactly(k)`, restrict results to channels that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl SetterSelector {
    /// Create a new selector that accepts all getter channels.
    pub fn new() -> Self {
        SetterSelector::default()
    }

    /// Selector to a channel with a specific id.
    pub fn with_id(self, id: Id<Setter>) -> Self {
        SetterSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific parent.
    pub fn with_parent(self, id: Id<ServiceId>) -> Self {
        SetterSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetterSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        SetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        SetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Setter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<Duration>,
    #[serde(default)]
    pub max: Option<Duration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x) |
            (x, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x) |
            (x, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x) |
            (x, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &Duration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        true
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<Duration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) => false,
            (&Some(_), &None) => false,
            _ => true,
        }
    }
}

fn has_selected_tags(actual: &HashSet<Id<TagId>>, requested: &HashSet<Id<TagId>>) -> bool {
    for tag in &*actual {
        if !requested.contains(tag) {
            return false;
        }
    }
    true
}
<commit_msg>[fxbox/taxonomy] Implementing select-by-parent-tag for channels<commit_after>use services::{ AdapterId, Service, ServiceId, ChannelKind, Channel, Getter, Setter, TagId };
use util::{ Exactly, Id };
use values::Duration;

use std::cmp;
use std::hash::Hash;
use std::collections::HashSet;

use serde::ser::Serializer;
use serde::de::Deserializer;

fn merge<T>(mut a: HashSet<T>, b: Vec<T>) -> HashSet<T> where T: Hash + Eq {
    for x in b {
        a.insert(x);
    }
    a
}

pub trait SelectedBy<T> {
    fn matches(&self, &T) -> bool;
}

/// A trait used to let ServiceSelector work on complex data structures
/// that are not necessarily exactly Selector.
pub trait ServiceLike {
    fn id(&self) -> &Id<ServiceId>;
    fn adapter(&self) -> &Id<AdapterId>;
    fn with_tags<F>(&self, f: F) -> bool where F: Fn(&HashSet<Id<TagId>>) -> bool;
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool;
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool;
}

impl ServiceLike for Service {
    fn id(&self) -> &Id<ServiceId> {
        &self.id
    }
    fn adapter(&self) -> &Id<AdapterId> {
        &self.adapter
    }
    fn with_tags<F>(&self, f: F) -> bool where F: Fn(&HashSet<Id<TagId>>) -> bool {
        f(&self.tags)
    }
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool {
        for chan in self.getters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool {
        for chan in self.setters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }

}

/// A selector for one or more services.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = ServiceSelector::new()
///   .with_tags(vec![Id::<TagId>::new("entrance")])
///   .with_getters(vec![GetterSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ServiceSelector {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<ServiceId>>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    /// Restrict results to services that have all the getters in `getters`.
    #[serde(default)]
    pub getters: Vec<GetterSelector>,

    /// Restrict results to services that have all the setters in `setters`.
    #[serde(default)]
    pub setters: Vec<SetterSelector>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl ServiceSelector {
    /// Create a new selector that accepts all services.
    pub fn new() -> Self {
        Self::default()
    }

    /// Selector for a service with a specific id.
    pub fn with_id(self, id: Id<ServiceId>) -> Self {
        ServiceSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        ServiceSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to services that have all the getters in `getters`.
    pub fn with_getters(mut self, mut getters: Vec<GetterSelector>) -> Self {
        ServiceSelector {
            getters: {self.getters.append(&mut getters); self.getters},
            .. self
        }
    }

    /// Restrict results to services that have all the setters in `setters`.
    pub fn with_setters(mut self, mut setters: Vec<SetterSelector>) -> Self {
        ServiceSelector {
            setters: {self.setters.append(&mut setters); self.setters},
            .. self
        }
    }

    /// Restrict results to services that are accepted by two selector.
    pub fn and(mut self, mut other: ServiceSelector) -> Self {
        ServiceSelector {
            id: self.id.and(other.id),
            tags: self.tags.union(&other.tags).cloned().collect(),
            getters: {self.getters.append(&mut other.getters); self.getters},
            setters: {self.setters.append(&mut other.setters); self.setters},
            private: (),
        }
    }

    pub fn matches<T>(&self, service: &T) -> bool
        where T: ServiceLike
    {
        if !self.id.matches(service.id()) {
            return false;
        }
        if !service.with_tags(|tags| has_selected_tags(&self.tags, tags)) {
            return false;
        }
        // If any of the getter selectors doesn't find a getter,
        // we don't match.
        let getters_fail = self.getters.iter().find(|selector| {
            !service.has_getters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if getters_fail {
            return false;
        }
        // If any of the setter selectors doesn't find a setter,
        // we don't match.
        let setters_fail = self.setters.iter().find(|selector| {
            !service.has_setters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if setters_fail {
            return false;
        }
        true
    }
}

impl SelectedBy<ServiceSelector> for Service {
    fn matches(&self, selector: &ServiceSelector) -> bool {
        selector.matches(self)
    }
}

/// A selector for one or more getter channels.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = GetterSelector::new()
///   .with_parent(Id::new("foxbox"))
///   .with_kind(ChannelKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GetterSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Getter>>,

    /// If `Eactly(id)`, return only channels that are children of
    /// service `id`.
    #[serde(default)]
    pub parent: Exactly<Id<ServiceId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

    /// If `Exatly(k)`, restrict results to channels that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl GetterSelector {
    /// Create a new selector that accepts all getter channels.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a channel with a specific id.
    pub fn with_id(self, id: Id<Getter>) -> Self {
        GetterSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific parent.
    pub fn with_parent(self, id: Id<ServiceId>) -> Self {
        GetterSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetterSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        GetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        GetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Getter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

/// A selector for one or more setter channels.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct SetterSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Setter>>,

    /// If `Exactly(id)`, return only channels that are immediate children
    /// of service `id`.
    #[serde(default)]
    pub parent: Exactly<Id<ServiceId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

    /// If `Exactly(k)`, restrict results to channels that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl SetterSelector {
    /// Create a new selector that accepts all getter channels.
    pub fn new() -> Self {
        SetterSelector::default()
    }

    /// Selector to a channel with a specific id.
    pub fn with_id(self, id: Id<Setter>) -> Self {
        SetterSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific parent.
    pub fn with_parent(self, id: Id<ServiceId>) -> Self {
        SetterSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetterSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<Id<TagId>>) -> Self {
        SetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        SetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Setter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<Duration>,
    #[serde(default)]
    pub max: Option<Duration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x) |
            (x, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x) |
            (x, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x) |
            (x, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &Duration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        true
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<Duration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) => false,
            (&Some(_), &None) => false,
            _ => true,
        }
    }
}

fn has_selected_tags(actual: &HashSet<Id<TagId>>, requested: &HashSet<Id<TagId>>) -> bool {
    for tag in &*actual {
        if !requested.contains(tag) {
            return false;
        }
    }
    true
}
<|endoftext|>


<commit_before>#![crate_name = "rmdir"]
#![feature(collections, core, old_io, old_path, rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::old_io::{print, fs};
use std::old_io::fs::PathExtensions;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "rmdir";

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();

    let opts = [
        getopts::optflag("", "ignore-fail-on-non-empty", "ignore each failure that is solely because a directory is non-empty"),
        getopts::optflag("p", "parents", "remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a"),
        getopts::optflag("v", "verbose", "output a diagnostic for every directory processed"),
        getopts::optflag("h", "help", "print this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            show_error!("{}", f);
            return 1;
        }
    };

    if matches.opt_present("help") {
        println!("rmdir 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... DIRECTORY...", program);
        println!("");
        print(getopts::usage("Remove the DIRECTORY(ies), if they are empty.", &opts).as_slice());
    } else if matches.opt_present("version") {
        println!("rmdir 1.0.0");
    } else if matches.free.is_empty() {
        show_error!("missing an argument");
        show_error!("for help, try '{0} --help'", program);
        return 1;
    } else {
        let ignore = matches.opt_present("ignore-fail-on-non-empty");
        let parents = matches.opt_present("parents");
        let verbose = matches.opt_present("verbose");
        match remove(matches.free, ignore, parents, verbose) {
            Ok(()) => ( /* pass */ ),
            Err(e) => return e
        }
    }

    0
}

fn remove(dirs: Vec<String>, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32>{
    let mut r = Ok(());

    for dir in dirs.iter() {
        let path = Path::new(dir.as_slice());
        if path.exists() {
            if path.is_dir() {
                r = remove_dir(&path, dir.as_slice(), ignore, parents, verbose).and(r);
            } else {
                show_error!("failed to remove '{}' (file)", *dir);
                r = Err(1);
            }
        } else {
            show_error!("no such file or directory '{}'", *dir);
            r = Err(1);
        }
    }

    r
}

fn remove_dir(path: &Path, dir: &str, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> {
    let mut walk_dir = match fs::walk_dir(path) {
        Ok(m) => m,
        Err(f) => {
            show_error!("{}", f.to_string());
            return Err(1);
        }
    };

    let mut r = Ok(());

    if walk_dir.next() == None {
        match fs::rmdir(path) {
            Ok(_) => {
                if verbose {
                    println!("Removed directory '{}'", dir);
                }
                if parents {
                    let dirname = path.dirname_str().unwrap();
                    if dirname != "." {
                        r = remove_dir(&Path::new(dirname), dirname, ignore, parents, verbose).and(r);
                    }
                }
            }
            Err(f) => {
                show_error!("{}", f.to_string());
                r = Err(1);
            }
        }
    } else if !ignore {
        show_error!("Failed to remove directory '{}' (non-empty)", dir);
        r = Err(1);
    }

    r
}
<commit_msg>fix `rmdir`<commit_after>#![crate_name = "rmdir"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::path::Path;
use std::io::Write;
use std::fs;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "rmdir";

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();

    let opts = [
        getopts::optflag("", "ignore-fail-on-non-empty", "ignore each failure that is solely because a directory is non-empty"),
        getopts::optflag("p", "parents", "remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a"),
        getopts::optflag("v", "verbose", "output a diagnostic for every directory processed"),
        getopts::optflag("h", "help", "print this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => {
            show_error!("{}", f);
            return 1;
        }
    };

    if matches.opt_present("help") {
        println!("rmdir 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... DIRECTORY...", program);
        println!("");
        println!("{}", &getopts::usage("Remove the DIRECTORY(ies), if they are empty.", &opts)[..]);
    } else if matches.opt_present("version") {
        println!("rmdir 1.0.0");
    } else if matches.free.is_empty() {
        show_error!("missing an argument");
        show_error!("for help, try '{0} --help'", program);
        return 1;
    } else {
        let ignore = matches.opt_present("ignore-fail-on-non-empty");
        let parents = matches.opt_present("parents");
        let verbose = matches.opt_present("verbose");
        match remove(matches.free, ignore, parents, verbose) {
            Ok(()) => ( /* pass */ ),
            Err(e) => return e
        }
    }

    0
}

fn remove(dirs: Vec<String>, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> {
    let mut r = Ok(());

    for dir in dirs.iter() {
        let path = Path::new(&dir[..]);
        r = remove_dir(&path, ignore, verbose).and(r);
        if parents {
            let mut p = path;
            loop {
                let new_p = match p.parent() {
                    Some(p) => p,
                    None => break,
                };
                p = new_p;

                match p.as_os_str().to_str() {
                    None => break,
                    Some(s) => match s {
                        "" | "." | "/" => break,
                        _ => (),
                    },
                };
                r = remove_dir(p, ignore, verbose).and(r);
            }
        }
    }

    r
}

fn remove_dir(path: &Path, ignore: bool, verbose: bool) -> Result<(), i32> {
    let mut read_dir = match fs::read_dir(path) {
        Ok(m) => m,
        Err(e) => {
            show_error!("reading directory '{}': {}", path.display(), e);
            return Err(1);
        }
    };

    let mut r = Ok(());

    if read_dir.next().is_none() {
        match fs::remove_dir(path) {
            Err(e) => {
                show_error!("removing directory '{}': {}", path.display(), e);
                r = Err(1);
            },
            Ok(_) if verbose => println!("Removed directory '{}'", path.display()),
            _ => (),
        }
    } else if !ignore {
        show_error!("failed to remove '{}' Directory not empty", path.display());
        r = Err(1);
    }

    r
}
<|endoftext|>


<commit_before>// Copyright 2018 Chao Lin & William Sergeant (Sorbonne University)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![macro_use]
use middle::analysis::ast::*;
use self::Pattern::*;
use self::Character::*;

#[derive(Copy, Clone)]
enum Pattern {
  // OneOrMore, // +
  // ZeroOrMore, // *
  // ZeroOrOne, // ?
  One,
  // And, // &
  // Not, // !
}

#[derive(Copy, Clone)]
enum Character{
  Char(char),
  Any // .
}

struct Occurence
{
  choice: Vec<Vec<(Character,Pattern)>>
}

impl Occurence
{
  fn push_sequence(&self, other: Occurence) -> Occurence{
    let mut res = vec![];
    for choice1 in other.choice.clone(){
      for choice2 in self.choice.clone(){
        let mut tmp = choice2.clone();
        for couple in choice1.clone(){
          tmp.push(couple)
        }
        res.push(tmp)
      }
    }
    Occurence{
      choice: res
    }
  }

  fn merge_choice(&self, other: Occurence) -> Occurence {
    let mut res = self.choice.clone();
    for choice in other.choice.clone(){
      res.push(choice)
    }
    Occurence{
      choice: res
    }
  }

  fn copy(&self) -> Occurence{
    Occurence{
      choice: self.choice.to_vec()
    }
  }

  fn is_unreachable_with(&self, target: Occurence) -> bool {
    let mut res = true;
    for seq in self.choice.clone(){
      if !(target.success_with(seq)) {
        res = false;
        break;
      }
    }
    res
  }

  fn success_with(&self, seq2: Vec<(Character, Pattern)>) -> bool {
    let mut res = false;
    for seq1 in self.choice.clone(){
      if self.succeed_before(seq1,seq2.to_vec()) {
        res = true;
      }
    }
    res
  }

  fn succeed_before(&self, seq1: Vec<(Character, Pattern)>, seq2: Vec<(Character, Pattern)>) -> bool{
    let mut res = true;
    if seq2.len()<seq1.len() {
      res=false;
    }
    else{
      for (i,character_pattern1) in seq1.iter().enumerate(){
        if let Some(character_pattern2) = seq2.get(i) {
          let &(c1,_p1) = character_pattern1;
          let &(c2,_p2) = character_pattern2;
          match c1 {
            Char(character1) => {
              match c2 {
                Char(character2) => {
                  if character1!=character2 {
                    res=false;
                    break;
                  }
                }
                Any => {
                  res=false;
                  break;
                }
              }
            }
            Any => { continue; }
          }
        }
      }
    }
    res
  }
}

pub struct UnreachableRule<'a: 'c, 'b: 'a, 'c>
{
  grammar: &'c AGrammar<'a, 'b>
}

impl <'a, 'b, 'c> UnreachableRule<'a, 'b, 'c>
{
  pub fn analyse(grammar: AGrammar<'a, 'b>) -> Partial<AGrammar<'a, 'b>> {
    UnreachableRule::check_unreachable_rule(&grammar);
    Partial::Value(grammar)
  }

  fn check_unreachable_rule(grammar: &'c AGrammar<'a, 'b>){
    let mut analyser = UnreachableRule{
      grammar: grammar
    };

    for rule in &grammar.rules {
      analyser.visit_expr(rule.expr_idx);
    }
  }
}

impl<'a, 'b, 'c> ExprByIndex for UnreachableRule<'a, 'b, 'c>
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.grammar.expr_by_index(index).clone()
  }
}

impl<'a, 'b, 'c> Visitor<Occurence> for UnreachableRule<'a, 'b, 'c>
{
  fn visit_choice(&mut self, _this: usize, children: Vec<usize>) -> Occurence{
    let mut occurences_of_children = vec![];
    for child in children.clone(){
      let occ = self.visit_expr(child);
      if !occ.choice.is_empty() {
          occurences_of_children.push((occ,child));
      }
    }
    for (i, cp1) in occurences_of_children.iter().enumerate(){
      let (_left, right) = occurences_of_children.split_at(i+1);
      let &(ref occ1, child1) = cp1;
      for cp2 in right{
        let &(ref occ2, child2) = cp2;
        if occ2.is_unreachable_with(occ1.copy()) {
          self.grammar.span_warn(
            self.grammar[child2].span(),
            format!("This rule is unreachable.")
          );
          self.grammar.span_note(
            self.grammar[child1].span(),
            format!("Because this rule succeeded before reading the previous one.")
          );
        }
      }
    }

    let mut res = vec![];
    if let Some((first, rest)) = children.split_first(){
      let mut occ = self.visit_expr(*first);
      for child in rest{
        occ = occ.merge_choice(self.visit_expr(*child))
      }
      res = occ.choice;
    }
    Occurence{
      choice: res
    }
  }

  fn visit_sequence(&mut self, _this: usize, children: Vec<usize>) -> Occurence{
    let mut res = vec![];
    if let Some((first, rest)) = children.split_first(){
      let mut occ = self.visit_expr(*first);
      for child in rest{
        occ = occ.push_sequence(self.visit_expr(*child))
      }
      res = occ.choice;
    }
    Occurence{
      choice: res
    }
  }

  fn visit_atom(&mut self, _this: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_str_literal(&mut self, _this: usize, lit: String) -> Occurence{
    let mut seq = vec![];
    for c in lit.chars(){
      seq.push((Char(c),One))
    }
    let mut res = vec![];
    res.push(seq);
    Occurence{
      choice: res
    }
  }

  fn visit_any_single_char(&mut self, _this: usize) -> Occurence{
    let mut seq = vec![];
    seq.push((Any,One));
    let mut res = vec![];
    res.push(seq);
    Occurence{
      choice: res
    }
  }

  fn visit_character_class(&mut self, _this: usize, _char_class: CharacterClassExpr) -> Occurence{
    // let mut seq = vec![];
    // for intervals in char_class.intervals{
    //   for intervals.lo to intervals.hi{
    //
    //   }
    // }
    Occurence{
      choice: vec![]
    }
  }

  fn visit_non_terminal_symbol(&mut self, _this: usize, _rule: Ident) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_zero_or_more(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_one_or_more(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_optional(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_not_predicate(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_and_predicate(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }
}
<commit_msg>[analysis] Add treatment of character class<commit_after>// Copyright 2018 Chao Lin & William Sergeant (Sorbonne University)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![macro_use]
use std::char::*;
use middle::analysis::ast::*;
use self::Pattern::*;
use self::Character::*;

#[derive(Copy, Clone)]
enum Pattern {
  // OneOrMore, // +
  // ZeroOrMore, // *
  // ZeroOrOne, // ?
  One,
  // And, // &
  // Not, // !
}

#[derive(Copy, Clone)]
enum Character{
  Char(char),
  Any // .
}

struct Occurence
{
  choice: Vec<Vec<(Character,Pattern)>>
}

impl Occurence
{
  fn push_sequence(&self, other: Occurence) -> Occurence{
    let mut res = vec![];
    for choice1 in other.choice.clone(){
      for choice2 in self.choice.clone(){
        let mut tmp = choice2.clone();
        for couple in choice1.clone(){
          tmp.push(couple)
        }
        res.push(tmp)
      }
    }
    Occurence{
      choice: res
    }
  }

  fn merge_choice(&self, other: Occurence) -> Occurence {
    let mut res = self.choice.clone();
    for choice in other.choice.clone(){
      res.push(choice)
    }
    Occurence{
      choice: res
    }
  }

  fn copy(&self) -> Occurence{
    Occurence{
      choice: self.choice.to_vec()
    }
  }

  fn is_unreachable_with(&self, target: Occurence) -> bool {
    let mut res = true;
    for seq in self.choice.clone(){
      if !(target.success_with(seq)) {
        res = false;
        break;
      }
    }
    res
  }

  fn success_with(&self, seq2: Vec<(Character, Pattern)>) -> bool {
    let mut res = false;
    for seq1 in self.choice.clone(){
      if self.succeed_before(seq1,seq2.to_vec()) {
        res = true;
      }
    }
    res
  }

  fn succeed_before(&self, seq1: Vec<(Character, Pattern)>, seq2: Vec<(Character, Pattern)>) -> bool{
    let mut res = true;
    if seq2.len()<seq1.len() {
      res=false;
    }
    else{
      for (i,character_pattern1) in seq1.iter().enumerate(){
        if let Some(character_pattern2) = seq2.get(i) {
          let &(c1,_p1) = character_pattern1;
          let &(c2,_p2) = character_pattern2;
          match c1 {
            Char(character1) => {
              match c2 {
                Char(character2) => {
                  if character1!=character2 {
                    res=false;
                    break;
                  }
                }
                Any => {
                  res=false;
                  break;
                }
              }
            }
            Any => { continue; }
          }
        }
      }
    }
    res
  }
}

pub struct UnreachableRule<'a: 'c, 'b: 'a, 'c>
{
  grammar: &'c AGrammar<'a, 'b>
}

impl <'a, 'b, 'c> UnreachableRule<'a, 'b, 'c>
{
  pub fn analyse(grammar: AGrammar<'a, 'b>) -> Partial<AGrammar<'a, 'b>> {
    UnreachableRule::check_unreachable_rule(&grammar);
    Partial::Value(grammar)
  }

  fn check_unreachable_rule(grammar: &'c AGrammar<'a, 'b>){
    let mut analyser = UnreachableRule{
      grammar: grammar
    };

    for rule in &grammar.rules {
      analyser.visit_expr(rule.expr_idx);
    }
  }
}

impl<'a, 'b, 'c> ExprByIndex for UnreachableRule<'a, 'b, 'c>
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.grammar.expr_by_index(index).clone()
  }
}

impl<'a, 'b, 'c> Visitor<Occurence> for UnreachableRule<'a, 'b, 'c>
{
  fn visit_choice(&mut self, _this: usize, children: Vec<usize>) -> Occurence{
    let mut occurences_of_children = vec![];
    for child in children.clone(){
      let occ = self.visit_expr(child);
      if !occ.choice.is_empty() {
          occurences_of_children.push((occ,child));
      }
    }
    for (i, cp1) in occurences_of_children.iter().enumerate(){
      let (_left, right) = occurences_of_children.split_at(i+1);
      let &(ref occ1, child1) = cp1;
      for cp2 in right{
        let &(ref occ2, child2) = cp2;
        if occ2.is_unreachable_with(occ1.copy()) {
          self.grammar.span_warn(
            self.grammar[child2].span(),
            format!("This alternative will nerver succeed.")
          );
          self.grammar.span_note(
            self.grammar[child1].span(),
            format!("Because this alternative succeeded before reaching the previous one.")
          );
        }
      }
    }

    let mut res = vec![];
    if let Some((first, rest)) = children.split_first(){
      let mut occ = self.visit_expr(*first);
      for child in rest{
        occ = occ.merge_choice(self.visit_expr(*child))
      }
      res = occ.choice;
    }
    Occurence{
      choice: res
    }
  }

  fn visit_sequence(&mut self, _this: usize, children: Vec<usize>) -> Occurence{
    let mut res = vec![];
    if let Some((first, rest)) = children.split_first(){
      let mut occ = self.visit_expr(*first);
      for child in rest{
        occ = occ.push_sequence(self.visit_expr(*child))
      }
      res = occ.choice;
    }
    Occurence{
      choice: res
    }
  }

  fn visit_atom(&mut self, _this: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_str_literal(&mut self, _this: usize, lit: String) -> Occurence{
    let mut seq = vec![];
    for c in lit.chars(){
      seq.push((Char(c),One))
    }
    let mut res = vec![];
    res.push(seq);
    Occurence{
      choice: res
    }
  }

  fn visit_any_single_char(&mut self, _this: usize) -> Occurence{
    let mut seq = vec![];
    seq.push((Any,One));
    let mut res = vec![];
    res.push(seq);
    Occurence{
      choice: res
    }
  }

  fn visit_character_class(&mut self, _this: usize, char_class: CharacterClassExpr) -> Occurence{
    let mut res = vec![];
    for intervals in char_class.intervals{
      for i in intervals.lo as u32 .. intervals.hi as u32 +1 {
        if let Some(c) = from_u32(i) {
          res.push(vec![(Char(c),One)])
        }
      }
    }
    Occurence{
      choice: res
    }
  }

  fn visit_non_terminal_symbol(&mut self, _this: usize, _rule: Ident) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_zero_or_more(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_one_or_more(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_optional(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_not_predicate(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }

  fn visit_and_predicate(&mut self, _this: usize, _child: usize) -> Occurence{
    Occurence{
      choice: vec![]
    }
  }
}
<|endoftext|>