<commit_before>macro_rules! iter_works_for {
    ($subject:ident) => {{
        let taps = vec![2, 3];
        let mut lfsr = $subject::from_iter(taps.iter());

        let iter = lfsr.iter();

        let output: Vec<bool> = iter.take(8).collect();

        let expected = vec![true, false, false, true, false, true, true, true];

        assert!($crate::support::eq_mod_rotation(&output, &expected));
    }}
}

macro_rules! primitive_connection_polynomial_yields_a_maximum_sequence {
    ($subject:ident) => {{
        let taps = vec![4, 5, 6, 8];

        let mut lfsr = $subject::from_iter(taps.iter());

        let bytes = lfsr.bytes();

        let mut result: Vec<u8> = bytes.take(1024).collect();
        result.sort();
        result.dedup();

        assert_eq!(result.len(), 255);
    }}
}

pub fn eq_mod_rotation<T: PartialEq>(left: &Vec<T>, right: &Vec<T>) -> bool {
    if left.len() != right.len() { return false }

    let len = left.len();

    for offset in 0 .. len {
        let cond = |i: usize| left[i] == right[(i + offset) % len];
        let equal = (0 .. len).all(cond);

        if equal { return true }
    }

    false
}

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

    #[test]
    fn eq_mod_rotation_works() {
        let v0: Vec<usize> = vec![1, 2, 3, 4];
        let v1: Vec<usize> = vec![2, 3, 4, 1];
        let v2: Vec<usize> = vec![3, 4, 1, 2];
        let v3: Vec<usize> = vec![4, 1, 2, 3];

        let w: Vec<usize> = vec![4, 3, 2, 1];

        assert!(eq_mod_rotation(&v0, &v0));
        assert!(eq_mod_rotation(&v0, &v1));
        assert!(eq_mod_rotation(&v0, &v2));
        assert!(eq_mod_rotation(&v0, &v3));

        assert!(eq_mod_rotation(&v1, &v1));
        assert!(eq_mod_rotation(&v1, &v2));
        assert!(eq_mod_rotation(&v1, &v3));

        assert!(eq_mod_rotation(&v2, &v2));
        assert!(eq_mod_rotation(&v2, &v3));

        assert!(eq_mod_rotation(&v3, &v3));

        assert!(!eq_mod_rotation(&v0, &w));
        assert!(!eq_mod_rotation(&v1, &w));
        assert!(!eq_mod_rotation(&v2, &w));
        assert!(!eq_mod_rotation(&v3, &w));
    }
}
<commit_msg>Add has_period predicate for output testing<commit_after>macro_rules! iter_works_for {
    ($subject:ident) => {{
        let taps = vec![2, 3];
        let mut lfsr = $subject::from_iter(taps.iter());

        let iter = lfsr.iter();

        let output: Vec<bool> = iter.take(8).collect();

        let expected = vec![true, false, false, true, false, true, true, true];

        assert!($crate::support::eq_mod_rotation(&output, &expected));
    }}
}

macro_rules! primitive_connection_polynomial_yields_a_maximum_sequence {
    ($subject:ident) => {{
        let taps = vec![4, 5, 6, 8];

        let mut lfsr = $subject::from_iter(taps.iter());

        let bytes = lfsr.bytes();

        let mut result: Vec<u8> = bytes.take(1024).collect();
        result.sort();
        result.dedup();

        assert_eq!(result.len(), 255);
    }}
}

pub fn eq_mod_rotation<T: PartialEq>(left: &Vec<T>, right: &Vec<T>) -> bool {
    if left.len() != right.len() { return false }

    let len = left.len();

    for offset in 0 .. len {
        let cond = |i: usize| left[i] == right[(i + offset) % len];
        let equal = (0 .. len).all(cond);

        if equal { return true }
    }

    false
}

pub fn has_period<T: PartialEq>(seq: &Vec<T>, n: usize) -> bool {
    let m = seq.len();

    (0 .. m).all(|i| seq[i] == seq[(i + n) % m])
}

#[cfg(test)]
mod test {
    use super::{eq_mod_rotation, has_period};

    #[test]
    fn eq_mod_rotation_works() {
        let v0: Vec<usize> = vec![1, 2, 3, 4];
        let v1: Vec<usize> = vec![2, 3, 4, 1];
        let v2: Vec<usize> = vec![3, 4, 1, 2];
        let v3: Vec<usize> = vec![4, 1, 2, 3];

        let w: Vec<usize> = vec![4, 3, 2, 1];

        assert!(eq_mod_rotation(&v0, &v0));
        assert!(eq_mod_rotation(&v0, &v1));
        assert!(eq_mod_rotation(&v0, &v2));
        assert!(eq_mod_rotation(&v0, &v3));

        assert!(eq_mod_rotation(&v1, &v1));
        assert!(eq_mod_rotation(&v1, &v2));
        assert!(eq_mod_rotation(&v1, &v3));

        assert!(eq_mod_rotation(&v2, &v2));
        assert!(eq_mod_rotation(&v2, &v3));

        assert!(eq_mod_rotation(&v3, &v3));

        assert!(!eq_mod_rotation(&v0, &w));
        assert!(!eq_mod_rotation(&v1, &w));
        assert!(!eq_mod_rotation(&v2, &w));
        assert!(!eq_mod_rotation(&v3, &w));
    }

    #[test]
    fn has_period_works() {
        let v_period_2 = vec![0, 1, 0, 1, 0, 1, 0, 1];
        let v_period_3 = vec![0, 1, 2, 0, 1, 2];

        let v_no_period = vec![0, 1, 0, 1, 0, 0];

        assert!(has_period(&v_period_2, 2));
        assert!(has_period(&v_period_3, 3));

        for i in 1 .. v_no_period.len() {
            assert!(!has_period(&v_no_period, i));
        }
    }
}
<|endoftext|>


<commit_before>#![no_std]
#![deny(unsafe_code)]

#[macro_use]
extern crate static_assertions;

assert_type_eq_all!([u8], [u8]);

#[allow(dead_code)]
type X = u8;

mod m {
    assert_type_eq_all!(super::X, u8, (super::X));
}
<commit_msg>Allow unused parentheses in `tests::type_eq`<commit_after>#![no_std]
#![deny(unsafe_code)]

#[macro_use]
extern crate static_assertions;

assert_type_eq_all!([u8], [u8]);

#[allow(dead_code)]
type X = u8;

#[allow(unused_parens)]
mod m {
    assert_type_eq_all!(super::X, u8, (super::X));
}
<|endoftext|>


<commit_before>use std::env;
use std::fmt;
use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
use std::sync::atomic;

use csv;

use Csv;

static XSV_INTEGRATION_TEST_DIR: &'static str = "xit";

static NEXT_ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Workdir {
    root: PathBuf,
    dir: PathBuf,
    flexible: bool,
}

impl Workdir {
    pub fn new(name: &str) -> Workdir {
        let id = NEXT_ID.fetch_add(1, atomic::Ordering::SeqCst);
        let root = env::current_exe().unwrap()
                       .parent()
                       .expect("executable's directory")
                       .to_path_buf();
        let dir = root.join(XSV_INTEGRATION_TEST_DIR)
                      .join(name)
                      .join(&format!("test-{}", id));
        if let Err(err) = create_dir_all(&dir) {
            panic!("Could not create '{:?}': {}", dir, err);
        }
        Workdir { root: root, dir: dir, flexible: false }
    }

    pub fn flexible(mut self, yes: bool) -> Workdir {
        self.flexible = yes;
        self
    }

    pub fn create<T: Csv>(&self, name: &str, rows: T) {
        let mut wtr = csv::Writer::from_file(&self.path(name)).unwrap();
        for row in rows.to_vecs().into_iter() {
            wtr.write(row.iter()).unwrap();
        }
        wtr.flush().unwrap();
    }

    pub fn create_indexed<T: Csv>(&self, name: &str, rows: T) {
        self.create(name, rows);

        let mut cmd = self.command("index");
        cmd.arg(name);
        self.run(&mut cmd);
    }

    pub fn read_stdout<T: Csv>(&self, cmd: &mut process::Command) -> T {
        let mut rdr = csv::Reader::from_string(self.stdout::<String>(cmd))
                                  .has_headers(false);
        Csv::from_vecs(rdr.records().collect::<Result<_, _>>().unwrap())
    }

    pub fn command(&self, sub_command: &str) -> process::Command {
        let mut cmd = process::Command::new(&self.xsv_bin());
        cmd.current_dir(&self.dir).arg(sub_command);
        cmd
    }

    pub fn output(&self, cmd: &mut process::Command) -> process::Output {
        debug!("[{}]: {:?}", self.dir.display(), cmd);
        let o = cmd.output().unwrap();
        if !o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command failed but expected success!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr))
        }
        o
    }

    pub fn run(&self, cmd: &mut process::Command) {
        self.output(cmd);
    }

    pub fn stdout<T: FromStr>(&self, cmd: &mut process::Command) -> T {
        let o = self.output(cmd);
        let stdout = String::from_utf8_lossy(&o.stdout);
        stdout.trim().parse().ok().expect(
            &format!("Could not convert from string: '{}'", stdout))
    }

    pub fn assert_err(&self, cmd: &mut process::Command) {
        let o = cmd.output().unwrap();
        if o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command succeeded but expected failure!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr));
        }
    }

    pub fn from_str<T: FromStr>(&self, name: &Path) -> T {
        let mut o = String::new();
        fs::File::open(name).unwrap().read_to_string(&mut o).unwrap();
        o.parse().ok().expect("fromstr")
    }

    pub fn path(&self, name: &str) -> PathBuf {
        self.dir.join(name)
    }

    pub fn xsv_bin(&self) -> PathBuf {
        self.root.join("xsv")
    }
}

impl fmt::Debug for Workdir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path={}", self.dir.display())
    }
}

// For whatever reason, `fs::create_dir_all` fails intermittently on Travis
// with a weird "file exists" error. Despite my best efforts to get to the
// bottom of it, I've decided a try-wait-and-retry hack is good enough.
fn create_dir_all<P: AsRef<Path>>(p: P) -> io::Result<()> {
    let mut last_err = None;
    for _ in 0..10 {
        if let Err(err) = fs::create_dir_all(&p) {
            last_err = Some(err);
            ::std::thread::sleep_ms(500);
        } else {
            return Ok(())
        }
    }
    Err(last_err.unwrap())
}
<commit_msg>Add forgotten config 'flexible'.<commit_after>use std::env;
use std::fmt;
use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
use std::sync::atomic;

use csv;

use Csv;

static XSV_INTEGRATION_TEST_DIR: &'static str = "xit";

static NEXT_ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Workdir {
    root: PathBuf,
    dir: PathBuf,
    flexible: bool,
}

impl Workdir {
    pub fn new(name: &str) -> Workdir {
        let id = NEXT_ID.fetch_add(1, atomic::Ordering::SeqCst);
        let root = env::current_exe().unwrap()
                       .parent()
                       .expect("executable's directory")
                       .to_path_buf();
        let dir = root.join(XSV_INTEGRATION_TEST_DIR)
                      .join(name)
                      .join(&format!("test-{}", id));
        if let Err(err) = create_dir_all(&dir) {
            panic!("Could not create '{:?}': {}", dir, err);
        }
        Workdir { root: root, dir: dir, flexible: false }
    }

    pub fn flexible(mut self, yes: bool) -> Workdir {
        self.flexible = yes;
        self
    }

    pub fn create<T: Csv>(&self, name: &str, rows: T) {
        let mut wtr = csv::Writer::from_file(&self.path(name))
                                  .unwrap().flexible(self.flexible);
        for row in rows.to_vecs().into_iter() {
            wtr.write(row.iter()).unwrap();
        }
        wtr.flush().unwrap();
    }

    pub fn create_indexed<T: Csv>(&self, name: &str, rows: T) {
        self.create(name, rows);

        let mut cmd = self.command("index");
        cmd.arg(name);
        self.run(&mut cmd);
    }

    pub fn read_stdout<T: Csv>(&self, cmd: &mut process::Command) -> T {
        let mut rdr = csv::Reader::from_string(self.stdout::<String>(cmd))
                                  .has_headers(false);
        Csv::from_vecs(rdr.records().collect::<Result<_, _>>().unwrap())
    }

    pub fn command(&self, sub_command: &str) -> process::Command {
        let mut cmd = process::Command::new(&self.xsv_bin());
        cmd.current_dir(&self.dir).arg(sub_command);
        cmd
    }

    pub fn output(&self, cmd: &mut process::Command) -> process::Output {
        debug!("[{}]: {:?}", self.dir.display(), cmd);
        let o = cmd.output().unwrap();
        if !o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command failed but expected success!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr))
        }
        o
    }

    pub fn run(&self, cmd: &mut process::Command) {
        self.output(cmd);
    }

    pub fn stdout<T: FromStr>(&self, cmd: &mut process::Command) -> T {
        let o = self.output(cmd);
        let stdout = String::from_utf8_lossy(&o.stdout);
        stdout.trim().parse().ok().expect(
            &format!("Could not convert from string: '{}'", stdout))
    }

    pub fn assert_err(&self, cmd: &mut process::Command) {
        let o = cmd.output().unwrap();
        if o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command succeeded but expected failure!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr));
        }
    }

    pub fn from_str<T: FromStr>(&self, name: &Path) -> T {
        let mut o = String::new();
        fs::File::open(name).unwrap().read_to_string(&mut o).unwrap();
        o.parse().ok().expect("fromstr")
    }

    pub fn path(&self, name: &str) -> PathBuf {
        self.dir.join(name)
    }

    pub fn xsv_bin(&self) -> PathBuf {
        self.root.join("xsv")
    }
}

impl fmt::Debug for Workdir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path={}", self.dir.display())
    }
}

// For whatever reason, `fs::create_dir_all` fails intermittently on Travis
// with a weird "file exists" error. Despite my best efforts to get to the
// bottom of it, I've decided a try-wait-and-retry hack is good enough.
fn create_dir_all<P: AsRef<Path>>(p: P) -> io::Result<()> {
    let mut last_err = None;
    for _ in 0..10 {
        if let Err(err) = fs::create_dir_all(&p) {
            last_err = Some(err);
            ::std::thread::sleep_ms(500);
        } else {
            return Ok(())
        }
    }
    Err(last_err.unwrap())
}
<|endoftext|>


<commit_before>pub fn parser_args(line: &str) -> Vec<(String, String)> {
    let mut result = Vec::new();
    let mut sep = String::new();
    let mut token = String::new();
    for c in line.chars() {
        if c == ' ' {
            if !sep.is_empty() {
                token.push(c);
                continue;
            }
            if token.is_empty() {
                continue;
            } else if sep.is_empty() {
                result.push((String::from(""), token));
                token = String::new();
                continue;
            } else {
                continue;
            }
        }
        if c == '\'' || c == '"' || c == '`' {
            if sep == "" {
                sep.push(c);
                continue;
            } else if sep == c.to_string() {
                result.push((c.to_string(), token));
                sep = String::new();
                token = String::new();
                continue;
            } else {
                token.push(c);
            }
        } else {
            token.push(c);
        }
    }
    if !token.is_empty() {
        result.push((String::from(""), token));
    }
    return result;
}

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

    #[test]
    fn test_parser_args() {
        assert_eq!(
            parser_args("ls"),
            vec![
                (String::from(""), String::from("ls")),
            ]
        );
        assert_eq!(
            parser_args("  ls  "),
            vec![
                (String::from(""), String::from("ls")),
            ]
        );
        assert_eq!(
            parser_args("ls -lh"),
            vec![
                ("".to_string(), "ls".to_string()),
                ("".to_string(), "-lh".to_string()),
            ]
        );
        assert_eq!(
            parser_args(" ls    -lh  "),
            vec![
                ("".to_string(), "ls".to_string()),
                ("".to_string(), "-lh".to_string()),
            ]
        );
        assert_eq!(
            parser_args("ls 'abc'"),
            vec![
                ("".to_string(), "ls".to_string()),
                ("\'".to_string(), "abc".to_string()),
            ]
        );
        assert_eq!(
            parser_args("ls \"abc\""),
            vec![
                ("".to_string(), "ls".to_string()),
                ("\"".to_string(), "abc".to_string()),
            ]
        );
        assert_eq!(
            parser_args("echo \"hi $USER\""),
            vec![
                ("".to_string(), "echo".to_string()),
                ("\"".to_string(), "hi $USER".to_string()),
            ]
        );
        assert_eq!(
            parser_args("echo \'hi $USER\'"),
            vec![
                ("".to_string(), "echo".to_string()),
                ("\'".to_string(), "hi $USER".to_string()),
            ]
        );
        assert_eq!(
            parser_args(" echo  \'hi $USER\'  |  wc  -l "),
            vec![
                ("".to_string(), "echo".to_string()),
                ("\'".to_string(), "hi $USER".to_string()),
                ("".to_string(), "|".to_string()),
                ("".to_string(), "wc".to_string()),
                ("".to_string(), "-l".to_string()),
            ]
        );
        assert_eq!(
            parser_args("echo `uname -m` | wc"),
            vec![
                ("".to_string(), "echo".to_string()),
                ("`".to_string(), "uname -m".to_string()),
                ("".to_string(), "|".to_string()),
                ("".to_string(), "wc".to_string()),
            ]
        );
        assert_eq!(
            parser_args("echo '`uname -m`'"),
            vec![
                ("".to_string(), "echo".to_string()),
                ("'".to_string(), "`uname -m`".to_string()),
            ]
        );
        assert_eq!(
            parser_args("'\"\"\"\"'"),
            vec![
                ("'".to_string(), "\"\"\"\"".to_string()),
            ]
        );
        assert_eq!(
            parser_args("\"\'\'\'\'\""),
            vec![
                ("\"".to_string(), "''''".to_string()),
            ]
        );
    }
}
<commit_msg>simplify tests<commit_after>pub fn parser_args(line: &str) -> Vec<(String, String)> {
    let mut result = Vec::new();
    let mut sep = String::new();
    let mut token = String::new();
    for c in line.chars() {
        if c == ' ' {
            if !sep.is_empty() {
                token.push(c);
                continue;
            }
            if token.is_empty() {
                continue;
            } else if sep.is_empty() {
                result.push((String::from(""), token));
                token = String::new();
                continue;
            } else {
                continue;
            }
        }
        if c == '\'' || c == '"' || c == '`' {
            if sep == "" {
                sep.push(c);
                continue;
            } else if sep == c.to_string() {
                result.push((c.to_string(), token));
                sep = String::new();
                token = String::new();
                continue;
            } else {
                token.push(c);
            }
        } else {
            token.push(c);
        }
    }
    if !token.is_empty() {
        result.push((String::from(""), token));
    }
    return result;
}

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

    fn _assert_vec_eq(a: Vec<(String, String)>, b: Vec<(&str, &str)>) {
        assert_eq!(a.len(), b.len());
        for (i, item) in a.iter().enumerate() {
            let (ref l, ref r) = *item;
            assert_eq!(l, b[i].0);
            assert_eq!(r, b[i].1);
        }
    }

    #[test]
    fn test_parser_args() {
        let v = vec![
            ("ls", vec![("", "ls")]),
            ("  ls   ", vec![("", "ls")]),
            ("ls -lh", vec![("", "ls"), ("", "-lh")]),
            ("  ls   -lh   ", vec![("", "ls"), ("", "-lh")]),
            ("ls 'abc'", vec![("", "ls"), ("'", "abc")]),
            ("ls \"abc\"", vec![("", "ls"), ("\"", "abc")]),
            ("echo \"hi $USER\"", vec![("", "echo"), ("\"", "hi $USER")]),
            ("echo 'hi $USER'", vec![("", "echo"), ("'", "hi $USER")]),
            ("echo 'hi $USER' |  wc  -l ", vec![("", "echo"),
                                                ("'", "hi $USER"),
                                                ("", "|"),
                                                ("", "wc"),
                                                ("", "-l")]),
            ("echo `uname -m` | wc", vec![("", "echo"),
                                                ("`", "uname -m"),
                                                ("", "|"),
                                                ("", "wc")]),
            ("echo '`uname -m`'", vec![("", "echo"), ("'", "`uname -m`")]),
            ("'\"\"\"\"'", vec![("'", "\"\"\"\"")]),
            ("\"\'\'\'\'\"", vec![("\"", "''''")]),
        ];
        for (left, right) in v {
            _assert_vec_eq(parser_args(left), right);
        }
    }
}
<|endoftext|>


<commit_before>//! Implements static board evaluation.

use std::hash::{Hasher, SipHasher};
use basetypes::*;
use bitsets::*;
use position::board::Board;

/// Statically evaluates the board.
///
/// This method considers only static material and positional
/// properties of the position. If the position is dynamic, with
/// pending tactical threats, this function will return a grossly
/// incorrect evaluation. Therefore, it should be relied upon only
/// for reasonably "quiet" positions.
///
/// `lower_bound` and `upper_bound` together give the interval
/// within which an as precise as possible evaluation is
/// required. If during the calculation it is determined that the
/// evaluation is outside this interval, this method may return
/// any value outside of the interval (including the bounds), but
/// always staying on the correct side of the interval.
#[inline]
pub fn evaluate_board(board: &Board, lower_bound: Value, upper_bound: Value) -> Value {
    assert!(lower_bound <= upper_bound);
    // TODO: Implement a real evaluation.

    const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

    let piece_type = board.piece_type();
    let color = board.color();
    let us = board.to_move();
    let them = 1 ^ us;
    let mut result = 0;
    for piece in QUEEN..NO_PIECE {
        result += PIECE_VALUES[piece] *
                  (pop_count(piece_type[piece] & color[us]) as i16 -
                   pop_count(piece_type[piece] & color[them]) as i16);
    }
    let mut hasher = SipHasher::new();
    hasher.write_u64(board.occupied());
    result + (hasher.finish() >> 59) as i16
}

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

<commit_msg>added doc<commit_after>//! Implements static board evaluation.

use std::hash::{Hasher, SipHasher};
use basetypes::*;
use bitsets::*;
use position::board::Board;

/// Statically evaluates the board.
///
/// This method considers only static material and positional
/// properties of the position. If the position is dynamic, with
/// pending tactical threats, this function will return a grossly
/// incorrect evaluation. Therefore, it should be relied upon only
/// for reasonably "quiet" positions.
///
/// `lower_bound` and `upper_bound` together give the interval
/// within which an as precise as possible evaluation is
/// required. If during the calculation it is determined that the
/// evaluation is outside this interval, this method may return
/// any value outside of the interval (including the bounds), but
/// always staying on the correct side of the interval.
///
/// The returned value will always be between -19999 and 19999.
#[inline]
pub fn evaluate_board(board: &Board, lower_bound: Value, upper_bound: Value) -> Value {
    assert!(lower_bound <= upper_bound);
    // TODO: Implement a real evaluation.

    const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

    let piece_type = board.piece_type();
    let color = board.color();
    let us = board.to_move();
    let them = 1 ^ us;
    let mut result = 0;
    for piece in QUEEN..NO_PIECE {
        result += PIECE_VALUES[piece] *
                  (pop_count(piece_type[piece] & color[us]) as i16 -
                   pop_count(piece_type[piece] & color[them]) as i16);
    }
    let mut hasher = SipHasher::new();
    hasher.write_u64(board.occupied());
    result + (hasher.finish() >> 59) as i16
}

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![allow(non_snake_case)]
#![allow(missing_copy_implementations)]

#![feature(phase)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

/// An actor-based remote devtools server implementation. Only tested with nightly Firefox
/// versions at time of writing. Largely based on reverse-engineering of Firefox chrome
/// devtool logs and reading of [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

extern crate collections;
extern crate core;
extern crate devtools_traits;
extern crate serialize;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use protocol::JsonPacketStream;

use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg, DevtoolsPageInfo};
use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;

use std::cell::RefCell;
use std::collections::HashMap;
use std::comm;
use std::comm::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut};
use std::sync::{Arc, Mutex};

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod inspector;
    pub mod root;
    pub mod tab;
}
mod protocol;

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = comm::channel();
    spawn_named("Devtools", proc() {
        run_server(receiver, port)
    });
    sender
}

static POLL_TIMEOUT: u64 = 300;

fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
    let listener = TcpListener::bind(format!("{}:{}", "127.0.0.1", port).as_slice());

    // bind the listener to the specified address
    let mut acceptor = listener.listen().unwrap();
    acceptor.set_timeout(Some(POLL_TIMEOUT));

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = Arc::new(Mutex::new(registry));

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_name().unwrap());
        {
            let actors = actors.lock();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(json_packet) => {
                    match actors.lock().handle_message(json_packet.as_object().unwrap(),
                                                       &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            let _ = stream.close_read();
                            let _ = stream.close_write();
                            break 'outer
                        }
                    }
                }
                Err(e) => {
                    println!("error: {}", e.desc);
                    break 'outer
                }
            }
        }
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         pipeline: PipelineId,
                         sender: Sender<DevtoolScriptControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>,
                         page_info: DevtoolsPageInfo) {
        let mut actors = actors.lock();

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: sender,
                pipeline: pipeline,
            };

            let DevtoolsPageInfo { title, url } = page_info;
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: title,
                url: url.serialize(),
                console: console.name(),
                inspector: inspector.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector)
        };

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
    }

    //TODO: figure out some system that allows us to watch for new connections,
    //      shut down existing ones at arbitrary times, and also watch for messages
    //      from multiple script tasks simultaneously. Polling for new connections
    //      for 300ms and then checking the receiver is not a good compromise
    //      (and makes Servo hang on exit if there's an open connection, no less).
    // accept connections and process them, spawning a new tasks for each one
    loop {
        match acceptor.accept() {
            Err(ref e) if e.kind == TimedOut => {
                match receiver.try_recv() {
                    Ok(ServerExitMsg) | Err(Disconnected) => break,
                    Ok(NewGlobal(id, sender, pageinfo)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines, pageinfo),
                    Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
                }
            }
            Err(_e) => { /* connection failed */ }
            Ok(stream) => {
                let actors = actors.clone();
                accepted_connections.push(stream.clone());
                spawn_named("DevtoolsClientHandler", proc() {
                    // connection succeeded
                    handle_client(actors, stream.clone())
                })
            }
        }
    }

    for connection in accepted_connections.iter_mut() {
        let _read = connection.close_read();
        let _write = connection.close_write();
    }
}
<commit_msg>Fix the documentation comment for the devtools library.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! An actor-based remote devtools server implementation. Only tested with
//! nightly Firefox versions at time of writing. Largely based on
//! reverse-engineering of Firefox chrome devtool logs and reading of
//! [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![allow(non_snake_case)]
#![allow(missing_copy_implementations)]

#![feature(phase)]

#[phase(plugin, link)]
extern crate log;

extern crate collections;
extern crate core;
extern crate devtools_traits;
extern crate serialize;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use protocol::JsonPacketStream;

use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg, DevtoolsPageInfo};
use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;

use std::cell::RefCell;
use std::collections::HashMap;
use std::comm;
use std::comm::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut};
use std::sync::{Arc, Mutex};

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod inspector;
    pub mod root;
    pub mod tab;
}
mod protocol;

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = comm::channel();
    spawn_named("Devtools", proc() {
        run_server(receiver, port)
    });
    sender
}

static POLL_TIMEOUT: u64 = 300;

fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
    let listener = TcpListener::bind(format!("{}:{}", "127.0.0.1", port).as_slice());

    // bind the listener to the specified address
    let mut acceptor = listener.listen().unwrap();
    acceptor.set_timeout(Some(POLL_TIMEOUT));

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = Arc::new(Mutex::new(registry));

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_name().unwrap());
        {
            let actors = actors.lock();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(json_packet) => {
                    match actors.lock().handle_message(json_packet.as_object().unwrap(),
                                                       &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            let _ = stream.close_read();
                            let _ = stream.close_write();
                            break 'outer
                        }
                    }
                }
                Err(e) => {
                    println!("error: {}", e.desc);
                    break 'outer
                }
            }
        }
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         pipeline: PipelineId,
                         sender: Sender<DevtoolScriptControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>,
                         page_info: DevtoolsPageInfo) {
        let mut actors = actors.lock();

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: sender,
                pipeline: pipeline,
            };

            let DevtoolsPageInfo { title, url } = page_info;
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: title,
                url: url.serialize(),
                console: console.name(),
                inspector: inspector.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector)
        };

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
    }

    //TODO: figure out some system that allows us to watch for new connections,
    //      shut down existing ones at arbitrary times, and also watch for messages
    //      from multiple script tasks simultaneously. Polling for new connections
    //      for 300ms and then checking the receiver is not a good compromise
    //      (and makes Servo hang on exit if there's an open connection, no less).
    // accept connections and process them, spawning a new tasks for each one
    loop {
        match acceptor.accept() {
            Err(ref e) if e.kind == TimedOut => {
                match receiver.try_recv() {
                    Ok(ServerExitMsg) | Err(Disconnected) => break,
                    Ok(NewGlobal(id, sender, pageinfo)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines, pageinfo),
                    Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
                }
            }
            Err(_e) => { /* connection failed */ }
            Ok(stream) => {
                let actors = actors.clone();
                accepted_connections.push(stream.clone());
                spawn_named("DevtoolsClientHandler", proc() {
                    // connection succeeded
                    handle_client(actors, stream.clone())
                })
            }
        }
    }

    for connection in accepted_connections.iter_mut() {
        let _read = connection.close_read();
        let _write = connection.close_write();
    }
}
<|endoftext|>


<commit_before>//! Waking mechanism for threads blocked on channel operations.

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, ThreadId};

use context::Context;
use select::{Operation, Selected};
use utils::Spinlock;

/// Represents a thread blocked on a specific channel operation.
pub struct Entry {
    /// The operation.
    pub oper: Operation,

    /// Optional packet.
    pub packet: usize,

    /// Context associated with the thread owning this operation.
    pub cx: Context,
}

/// A queue of threads blocked on channel operations.
///
/// This data structure is used by threads to register blocking operations and get woken up once
/// an operation becomes ready.
pub struct Waker {
    /// A list of select operations.
    selectors: Vec<Entry>,

    /// A list of operations waiting to be ready.
    observers: Vec<Entry>,
}

impl Waker {
    /// Creates a new `Waker`.
    #[inline]
    pub fn new() -> Self {
        Waker {
            selectors: Vec::new(),
            observers: Vec::new(),
        }
    }

    /// Registers a select operation.
    #[inline]
    pub fn register(&mut self, oper: Operation, cx: &Context) {
        self.register_with_packet(oper, 0, cx);
    }

    /// Registers a select operation and a packet.
    #[inline]
    pub fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
        self.selectors.push(Entry {
            oper,
            packet,
            cx: cx.clone(),
        });
    }

    /// Unregisters a select operation.
    #[inline]
    pub fn unregister(&mut self, oper: Operation) -> Option<Entry> {
        if let Some((i, _)) = self
            .selectors
            .iter()
            .enumerate()
            .find(|&(_, entry)| entry.oper == oper)
        {
            let entry = self.selectors.remove(i);
            Some(entry)
        } else {
            None
        }
    }

    /// Attempts to find another thread's entry, select the operation, and wake it up.
    #[inline]
    pub fn try_select(&mut self) -> Option<Entry> {
        let mut entry = None;

        if !self.selectors.is_empty() {
            let thread_id = current_thread_id();

            for i in 0..self.selectors.len() {
                // Does the entry belong to a different thread?
                if self.selectors[i].cx.thread_id() != thread_id {
                    // Try selecting this operation.
                    let sel = Selected::Operation(self.selectors[i].oper);
                    let res = self.selectors[i].cx.try_select(sel);

                    if res.is_ok() {
                        // Provide the packet.
                        self.selectors[i].cx.store_packet(self.selectors[i].packet);
                        // Wake the thread up.
                        self.selectors[i].cx.unpark();

                        // Remove the entry from the queue to keep it clean and improve
                        // performance.
                        entry = Some(self.selectors.remove(i));
                        break;
                    }
                }
            }
        }

        entry
    }

    /// Returns `true` if there is an entry which can be selected by the current thread.
    #[inline]
    pub fn can_select(&self) -> bool {
        if self.selectors.is_empty() {
            false
        } else {
            let thread_id = current_thread_id();

            self.selectors.iter().any(|entry| {
                entry.cx.thread_id() != thread_id && entry.cx.selected() == Selected::Waiting
            })
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub fn watch(&mut self, oper: Operation, cx: &Context) {
        self.observers.push(Entry {
            oper,
            packet: 0,
            cx: cx.clone(),
        });
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub fn unwatch(&mut self, oper: Operation) {
        self.observers.retain(|e| e.oper != oper);
    }

    /// Notifies all operations waiting to be ready.
    #[inline]
    pub fn notify(&mut self) {
        for entry in self.observers.drain(..) {
            if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() {
                entry.cx.unpark();
            }
        }
    }

    /// Notifies all registered operations that the channel is disconnected.
    #[inline]
    pub fn disconnect(&mut self) {
        for entry in self.selectors.iter() {
            if entry.cx.try_select(Selected::Disconnected).is_ok() {
                // Wake the thread up.
                //
                // Here we don't remove the entry from the queue. Registered threads must
                // unregister from the waker by themselves. They might also want to recover the
                // packet value and destroy it, if necessary.
                entry.cx.unpark();
            }
        }

        self.notify();
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.selectors.len(), 0);
        debug_assert_eq!(self.observers.len(), 0);
    }
}

/// A waker that can be shared among threads without locking.
///
/// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
pub struct SyncWaker {
    /// The inner `Waker`.
    inner: Spinlock<Waker>,

    /// `true` if the waker is empty.
    is_empty: AtomicBool,
}

impl SyncWaker {
    /// Creates a new `SyncWaker`.
    #[inline]
    pub fn new() -> Self {
        SyncWaker {
            inner: Spinlock::new(Waker::new()),
            is_empty: AtomicBool::new(true),
        }
    }

    /// Registers the current thread with an operation.
    #[inline]
    pub fn register(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.register(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation previously registered by the current thread.
    #[inline]
    pub fn unregister(&self, oper: Operation) -> Option<Entry> {
        let mut inner = self.inner.lock();
        let entry = inner.unregister(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
        entry
    }

    /// Attempts to find one thread (not the current one), select its operation, and wake it up.
    #[inline]
    pub fn notify(&self) {
        if !self.is_empty.load(Ordering::SeqCst) {
            let mut inner = self.inner.lock();
            inner.try_select();
            inner.notify();
            self.is_empty.store(
                inner.selectors.is_empty() && inner.observers.is_empty(),
                Ordering::SeqCst,
            );
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub fn watch(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.watch(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub fn unwatch(&self, oper: Operation) {
        let mut inner = self.inner.lock();
        inner.unwatch(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Notifies all threads that the channel is disconnected.
    #[inline]
    pub fn disconnect(&self) {
        let mut inner = self.inner.lock();
        inner.disconnect();
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }
}

impl Drop for SyncWaker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.is_empty.load(Ordering::SeqCst), true);
    }
}

/// Returns the id of the current thread.
#[inline]
fn current_thread_id() -> ThreadId {
    thread_local! {
        /// Cached thread-local id.
        static THREAD_ID: ThreadId = thread::current().id();
    }

    THREAD_ID
        .try_with(|id| *id)
        .unwrap_or_else(|_| thread::current().id())
}
<commit_msg>channel: call notify only from one thread<commit_after>//! Waking mechanism for threads blocked on channel operations.

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, ThreadId};

use context::Context;
use select::{Operation, Selected};
use utils::Spinlock;

/// Represents a thread blocked on a specific channel operation.
pub struct Entry {
    /// The operation.
    pub oper: Operation,

    /// Optional packet.
    pub packet: usize,

    /// Context associated with the thread owning this operation.
    pub cx: Context,
}

/// A queue of threads blocked on channel operations.
///
/// This data structure is used by threads to register blocking operations and get woken up once
/// an operation becomes ready.
pub struct Waker {
    /// A list of select operations.
    selectors: Vec<Entry>,

    /// A list of operations waiting to be ready.
    observers: Vec<Entry>,
}

impl Waker {
    /// Creates a new `Waker`.
    #[inline]
    pub fn new() -> Self {
        Waker {
            selectors: Vec::new(),
            observers: Vec::new(),
        }
    }

    /// Registers a select operation.
    #[inline]
    pub fn register(&mut self, oper: Operation, cx: &Context) {
        self.register_with_packet(oper, 0, cx);
    }

    /// Registers a select operation and a packet.
    #[inline]
    pub fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
        self.selectors.push(Entry {
            oper,
            packet,
            cx: cx.clone(),
        });
    }

    /// Unregisters a select operation.
    #[inline]
    pub fn unregister(&mut self, oper: Operation) -> Option<Entry> {
        if let Some((i, _)) = self
            .selectors
            .iter()
            .enumerate()
            .find(|&(_, entry)| entry.oper == oper)
        {
            let entry = self.selectors.remove(i);
            Some(entry)
        } else {
            None
        }
    }

    /// Attempts to find another thread's entry, select the operation, and wake it up.
    #[inline]
    pub fn try_select(&mut self) -> Option<Entry> {
        let mut entry = None;

        if !self.selectors.is_empty() {
            let thread_id = current_thread_id();

            for i in 0..self.selectors.len() {
                // Does the entry belong to a different thread?
                if self.selectors[i].cx.thread_id() != thread_id {
                    // Try selecting this operation.
                    let sel = Selected::Operation(self.selectors[i].oper);
                    let res = self.selectors[i].cx.try_select(sel);

                    if res.is_ok() {
                        // Provide the packet.
                        self.selectors[i].cx.store_packet(self.selectors[i].packet);
                        // Wake the thread up.
                        self.selectors[i].cx.unpark();

                        // Remove the entry from the queue to keep it clean and improve
                        // performance.
                        entry = Some(self.selectors.remove(i));
                        break;
                    }
                }
            }
        }

        entry
    }

    /// Returns `true` if there is an entry which can be selected by the current thread.
    #[inline]
    pub fn can_select(&self) -> bool {
        if self.selectors.is_empty() {
            false
        } else {
            let thread_id = current_thread_id();

            self.selectors.iter().any(|entry| {
                entry.cx.thread_id() != thread_id && entry.cx.selected() == Selected::Waiting
            })
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub fn watch(&mut self, oper: Operation, cx: &Context) {
        self.observers.push(Entry {
            oper,
            packet: 0,
            cx: cx.clone(),
        });
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub fn unwatch(&mut self, oper: Operation) {
        self.observers.retain(|e| e.oper != oper);
    }

    /// Notifies all operations waiting to be ready.
    #[inline]
    pub fn notify(&mut self) {
        for entry in self.observers.drain(..) {
            if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() {
                entry.cx.unpark();
            }
        }
    }

    /// Notifies all registered operations that the channel is disconnected.
    #[inline]
    pub fn disconnect(&mut self) {
        for entry in self.selectors.iter() {
            if entry.cx.try_select(Selected::Disconnected).is_ok() {
                // Wake the thread up.
                //
                // Here we don't remove the entry from the queue. Registered threads must
                // unregister from the waker by themselves. They might also want to recover the
                // packet value and destroy it, if necessary.
                entry.cx.unpark();
            }
        }

        self.notify();
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.selectors.len(), 0);
        debug_assert_eq!(self.observers.len(), 0);
    }
}

/// A waker that can be shared among threads without locking.
///
/// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
pub struct SyncWaker {
    /// The inner `Waker`.
    inner: Spinlock<Waker>,

    /// `true` if the waker is empty.
    is_empty: AtomicBool,
}

impl SyncWaker {
    /// Creates a new `SyncWaker`.
    #[inline]
    pub fn new() -> Self {
        SyncWaker {
            inner: Spinlock::new(Waker::new()),
            is_empty: AtomicBool::new(true),
        }
    }

    /// Registers the current thread with an operation.
    #[inline]
    pub fn register(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.register(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation previously registered by the current thread.
    #[inline]
    pub fn unregister(&self, oper: Operation) -> Option<Entry> {
        let mut inner = self.inner.lock();
        let entry = inner.unregister(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
        entry
    }

    /// Attempts to find one thread (not the current one), select its operation, and wake it up.
    #[inline]
    pub fn notify(&self) {
        if !self.is_empty.load(Ordering::SeqCst) {
            let mut inner = self.inner.lock();
            if !self.is_empty.load(Ordering::SeqCst) {
                inner.try_select();
                inner.notify();
                self.is_empty.store(
                    inner.selectors.is_empty() && inner.observers.is_empty(),
                    Ordering::SeqCst,
                );
            }
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub fn watch(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.watch(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub fn unwatch(&self, oper: Operation) {
        let mut inner = self.inner.lock();
        inner.unwatch(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Notifies all threads that the channel is disconnected.
    #[inline]
    pub fn disconnect(&self) {
        let mut inner = self.inner.lock();
        inner.disconnect();
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }
}

impl Drop for SyncWaker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.is_empty.load(Ordering::SeqCst), true);
    }
}

/// Returns the id of the current thread.
#[inline]
fn current_thread_id() -> ThreadId {
    thread_local! {
        /// Cached thread-local id.
        static THREAD_ID: ThreadId = thread::current().id();
    }

    THREAD_ID
        .try_with(|id| *id)
        .unwrap_or_else(|_| thread::current().id())
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use ir::{Program, Function, Block, BlockId, Instruction, BlockEnd};
use super::Rewriter;

struct RemoveNops;

impl Rewriter for RemoveNops {
    fn rewrite_block(&mut self, _id: BlockId, block: &mut Block) {
        block.ops.retain(|o| if let Instruction::Nop = *o {
            false
        } else {
            true
        });
    }
}

struct ShortenUnreachable;

impl Rewriter for ShortenUnreachable {
    fn rewrite_block(&mut self, _id: BlockId, block: &mut Block) {
        let mut to_keep = None;
        for (index, op) in block.ops.iter().enumerate() {
            if let Instruction::Unreachable = *op {
                to_keep = Some(index);
            }
        }
        if let Some(index) = to_keep {
            block.ops.truncate(index);
            block.end = BlockEnd::Unreachable;
        }
    }
}

#[derive(Default)]
struct JoinBlocks {
    references: HashMap<BlockId, u32>,
}

impl Rewriter for JoinBlocks {
    fn rewrite_function(&mut self, f: &mut Function) {
        self.references.clear();
        for block in f.blocks.values() {
            match block.end {
                BlockEnd::Branch(_, a, b) => {
                    *self.references.entry(a).or_insert(0) += 1;
                    *self.references.entry(b).or_insert(0) += 1;
                }
                BlockEnd::Jump(a) => {
                    *self.references.entry(a).or_insert(0) += 1;
                }
                BlockEnd::Return(_) |
                BlockEnd::ReturnProc |
                BlockEnd::Unreachable => {}
            }
        }
        if let Some(block) = f.start_block {
            *self.references.entry(block).or_insert(0) += 1;
        }
        loop {
            enum Change {
                Remove(BlockId),
                Join(BlockId, BlockId),
                None,
            }
            let mut change = Change::None;
            for (&id, block) in &f.blocks {
                if *self.references.entry(id).or_insert(0) == 0 {
                    change = Change::Remove(id);
                    break;
                }
                if let BlockEnd::Jump(to) = block.end {
                    if *self.references.entry(to).or_insert(0) == 1 {
                        change = if id == to {
                            Change::Remove(id)
                        } else {
                            Change::Join(id, to)
                        };
                        break;
                    }
                }
            }
            match change {
                Change::Join(a, b) => {
                    let removed = f.blocks.remove(&b).unwrap();
                    let first = f.blocks.get_mut(&a).unwrap();
                    first.ops.extend(removed.ops);
                    match first.end {
                        BlockEnd::Branch(_, a, b) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                            *self.references.get_mut(&b).unwrap() -= 1;
                        }
                        BlockEnd::Jump(a) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                        }
                        BlockEnd::Return(_) |
                        BlockEnd::ReturnProc |
                        BlockEnd::Unreachable => {}
                    }
                    first.end = removed.end;
                }
                Change::Remove(block) => {
                    let block = f.blocks.remove(&block).unwrap();
                    match block.end {
                        BlockEnd::Branch(_, a, b) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                            *self.references.get_mut(&b).unwrap() -= 1;
                        }
                        BlockEnd::Jump(a) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                        }
                        BlockEnd::Return(_) |
                        BlockEnd::ReturnProc |
                        BlockEnd::Unreachable => {}
                    }
                }
                Change::None => break,
            }
        }
    }
}

pub fn rewrite(program: &mut Program) {
    RemoveNops.rewrite_program(program);
    JoinBlocks::default().rewrite_program(program);
    ShortenUnreachable.rewrite_program(program);
}
<commit_msg>remove unused registers<commit_after>use std::collections::{HashMap, HashSet};
use analysis::Loc;
use ir::{Program, Function, Block, BlockId, Instruction, BlockEnd, Value, Reg};
use super::Rewriter;

struct RemoveNops;

impl Rewriter for RemoveNops {
    fn rewrite_block(&mut self, _id: BlockId, block: &mut Block) {
        block.ops.retain(|o| if let Instruction::Nop = *o {
            false
        } else {
            true
        });
    }
}

struct ShortenUnreachable;

impl Rewriter for ShortenUnreachable {
    fn rewrite_block(&mut self, _id: BlockId, block: &mut Block) {
        let mut to_keep = None;
        for (index, op) in block.ops.iter().enumerate() {
            if let Instruction::Unreachable = *op {
                to_keep = Some(index);
            }
        }
        if let Some(index) = to_keep {
            block.ops.truncate(index);
            block.end = BlockEnd::Unreachable;
        }
    }
}

#[derive(Default)]
struct JoinBlocks {
    references: HashMap<BlockId, u32>,
}

impl Rewriter for JoinBlocks {
    fn rewrite_function(&mut self, f: &mut Function) {
        self.references.clear();
        for block in f.blocks.values() {
            match block.end {
                BlockEnd::Branch(_, a, b) => {
                    *self.references.entry(a).or_insert(0) += 1;
                    *self.references.entry(b).or_insert(0) += 1;
                }
                BlockEnd::Jump(a) => {
                    *self.references.entry(a).or_insert(0) += 1;
                }
                BlockEnd::Return(_) |
                BlockEnd::ReturnProc |
                BlockEnd::Unreachable => {}
            }
        }
        if let Some(block) = f.start_block {
            *self.references.entry(block).or_insert(0) += 1;
        }
        loop {
            enum Change {
                Remove(BlockId),
                Join(BlockId, BlockId),
                None,
            }
            let mut change = Change::None;
            for (&id, block) in &f.blocks {
                if *self.references.entry(id).or_insert(0) == 0 {
                    change = Change::Remove(id);
                    break;
                }
                if let BlockEnd::Jump(to) = block.end {
                    if *self.references.entry(to).or_insert(0) == 1 {
                        change = if id == to {
                            Change::Remove(id)
                        } else {
                            Change::Join(id, to)
                        };
                        break;
                    }
                }
            }
            match change {
                Change::Join(a, b) => {
                    let removed = f.blocks.remove(&b).unwrap();
                    let first = f.blocks.get_mut(&a).unwrap();
                    first.ops.extend(removed.ops);
                    match first.end {
                        BlockEnd::Branch(_, a, b) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                            *self.references.get_mut(&b).unwrap() -= 1;
                        }
                        BlockEnd::Jump(a) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                        }
                        BlockEnd::Return(_) |
                        BlockEnd::ReturnProc |
                        BlockEnd::Unreachable => {}
                    }
                    first.end = removed.end;
                }
                Change::Remove(block) => {
                    let block = f.blocks.remove(&block).unwrap();
                    match block.end {
                        BlockEnd::Branch(_, a, b) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                            *self.references.get_mut(&b).unwrap() -= 1;
                        }
                        BlockEnd::Jump(a) => {
                            *self.references.get_mut(&a).unwrap() -= 1;
                        }
                        BlockEnd::Return(_) |
                        BlockEnd::ReturnProc |
                        BlockEnd::Unreachable => {}
                    }
                }
                Change::None => break,
            }
        }
    }
}

#[derive(Default)]
struct RemoveUnusedRegs {
    used: HashSet<Reg>,
}

impl RemoveUnusedRegs {
    fn track(&mut self, reg: Reg) {
        self.used.insert(reg);
    }

    fn track_val(&mut self, val: &Value) {
        if let Value::Reg(r) = *val {
            self.track(r);
        }
    }

    fn track_values(&mut self, values: &[Value]) {
        for val in values {
            self.track_val(val);
        }
    }
}

impl Rewriter for RemoveUnusedRegs {
    fn rewrite_function(&mut self, f: &mut Function) {
        self.used.clear();
        super::rewrite_function(self, f);
        for &r in &f.parameters {
            self.track(r);
        }
        f.registers.retain(|&r, _| self.used.contains(&r));
    }

    fn rewrite_instruction(&mut self, _loc: Loc, instr: &mut Instruction) {
        match *instr {
            Instruction::Assign(r, ref val) |
            Instruction::CastAssign(r, ref val) |
            Instruction::DerefLoad(r, ref val, _) |
            Instruction::Store(r, _, ref val) |
            Instruction::UnaryOp(r, _, ref val) => {
                self.track(r);
                self.track_val(val);
            }
            Instruction::BinaryOp(r, _, ref a, ref b) => {
                self.track(r);
                self.track_val(a);
                self.track_val(b);
            }
            Instruction::Call(r, _, ref params) => {
                self.track(r);
                self.track_values(params);
            }
            Instruction::CallProc(_, ref params) => {
                self.track_values(params);
            }
            Instruction::CallProcVirt(ref f, ref params) => {
                self.track_val(f);
                self.track_values(params);
            }
            Instruction::CallVirt(r, ref f, ref params) => {
                self.track(r);
                self.track_val(f);
                self.track_values(params);
            }
            Instruction::DerefStore(ref a, _, ref b) => {
                self.track_val(a);
                self.track_val(b);
            }
            Instruction::Drop(r) |
            Instruction::Init(r) => {
                self.track(r);
            }
            Instruction::Load(r1, r2, _) |
            Instruction::TakeAddress(r1, r2, _) => {
                self.track(r1);
                self.track(r2);
            }
            Instruction::Nop |
            Instruction::Unreachable => {}
        }
    }
}

pub fn rewrite(program: &mut Program) {
    RemoveNops.rewrite_program(program);
    JoinBlocks::default().rewrite_program(program);
    ShortenUnreachable.rewrite_program(program);
    RemoveUnusedRegs::default().rewrite_program(program);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs::File;
use std::ops::Drop;
use std::path::PathBuf;
use std::result::Result as RResult;
use std::sync::Arc;
use std::sync::{RwLock, Mutex};

use fs2::FileExt;

use entry::Entry;
use error::StoreError;

pub type Result<T> = RResult<T, StoreError>;

pub type StoreId = PathBuf;

trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl<'a> IntoStoreId for &'a str {
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl<'a> IntoStoreId for &'a String{
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl IntoStoreId for String{
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

impl<'a> IntoStoreId for &'a PathBuf {
    fn into_storeid(self) -> StoreId {
        self.clone()
    }
}

impl<ISI: IntoStoreId> IntoStoreId for (ISI, ISI) {
    fn into_storeid(self) -> StoreId {
        let (first, second) = self;
        let mut res : StoreId = first.into_storeid();
        res.push(second.into_storeid());
        res
    }
}

struct StoreEntry {
    file: File,
    entry: Option<Entry>,
}

impl StoreEntry {
    fn is_borrowed(&self) -> bool {
        self.entry.is_none()
    }

    fn set_entry(&mut self, entry: Entry) -> Result<()> {
        self.entry = Some(entry);
        unimplemented!()
    }

    fn get_entry(&mut self) -> Result<Entry> {
        unimplemented!()
    }
}

pub struct Store {
    location: PathBuf,

    /**
     * Internal Path->File cache map
     *
     * Caches the files, so they remain flock()ed
     *
     * Could be optimized for a threadsafe HashMap
     */
    entries: Arc<RwLock<HashMap<StoreId, StoreEntry>>>,
}

impl Store {
    pub fn create(&self, entry: Entry) -> Result<()> {
        unimplemented!();
    }

    pub fn retrieve<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> {
        unimplemented!();
    }

    pub fn update<'a>(&'a self, entry: FileLockEntry<'a>) -> Result<()> {
        unimplemented!();
    }

    pub fn retrieve_copy(&self, id: StoreId) -> Result<Entry> {
        unimplemented!();
    }

    pub fn delete(&self, id: StoreId) -> Result<()> {
        unimplemented!();
    }
}

impl Drop for Store {

    /**
     * Unlock all files on drop
     *
     * TODO: Error message when file cannot be unlocked?
     */
    fn drop(&mut self) {
        self.entries.write().unwrap()
            .iter().map(|f| f.1.file.unlock());
    }

}

pub struct FileLockEntry<'a> {
    store: &'a Store,
    entry: Entry,
    key: StoreId,
}

impl<'a> FileLockEntry<'a, > {
    fn new(store: &'a Store, entry: Entry, key: StoreId) -> FileLockEntry<'a> {
        FileLockEntry {
            store: store,
            entry: entry,
            key: key,
        }
    }
}

impl<'a> ::std::ops::Deref for FileLockEntry<'a> {
    type Target = Entry;

    fn deref(&self) -> &Self::Target {
        &self.entry
    }
}

impl<'a> ::std::ops::DerefMut for FileLockEntry<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.entry
    }
}

impl<'a> Drop for FileLockEntry<'a> {
    fn drop(&mut self) {
        let mut map = self.store.entries.write().unwrap();
        map.get_mut(&self.key).unwrap().set_entry(self.entry.clone());
    }
}

#[cfg(test)]
mod test {
    use std::path::PathBuf;
    use store::{StoreId, IntoStoreId};

    #[test]
    fn into_storeid_trait() {
        let buf = PathBuf::from("abc/def");

        let test = ("abc", "def");
        assert_eq!(buf, test.into_storeid());

        let test = "abc/def";
        assert_eq!(buf, test.into_storeid());

        let test = String::from("abc/def");
        assert_eq!(buf, test.into_storeid());

        let test = PathBuf::from("abc/def");
        assert_eq!(buf, test.into_storeid());
    }
}

<commit_msg>Add documentation to src/store.rs<commit_after>use std::collections::HashMap;
use std::fs::File;
use std::ops::Drop;
use std::path::PathBuf;
use std::result::Result as RResult;
use std::sync::Arc;
use std::sync::{RwLock, Mutex};

use fs2::FileExt;

use entry::Entry;
use error::StoreError;

/// The Result Type returned by any interaction with the store that could fail
pub type Result<T> = RResult<T, StoreError>;

/// The Index into the Store
pub type StoreId = PathBuf;

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl<'a> IntoStoreId for &'a str {
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl<'a> IntoStoreId for &'a String{
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl IntoStoreId for String{
    fn into_storeid(self) -> StoreId {
        PathBuf::from(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

impl<'a> IntoStoreId for &'a PathBuf {
    fn into_storeid(self) -> StoreId {
        self.clone()
    }
}

impl<ISI: IntoStoreId> IntoStoreId for (ISI, ISI) {
    fn into_storeid(self) -> StoreId {
        let (first, second) = self;
        let mut res : StoreId = first.into_storeid();
        res.push(second.into_storeid());
        res
    }
}

/// A store entry, depending on the option type it is either borrowed currently
/// or not.
struct StoreEntry {
    file: File,
    entry: Option<Entry>,
}

impl StoreEntry {
    /// The entry is currently borrowed, meaning that some thread is currently
    /// mutating it
    fn is_borrowed(&self) -> bool {
        self.entry.is_none()
    }

    /// Set the entry to the given one. This will also overwrite the entry
    /// and flush it to disk
    fn set_entry(&mut self, entry: Entry) -> Result<()> {
        self.entry = Some(entry);
        unimplemented!()
    }

    /// We borrow the entry
    fn get_entry(&mut self) -> Result<Entry> {
        unimplemented!()
    }
}

/// The Store itself, through this object one can interact with IMAG's entries
pub struct Store {
    location: PathBuf,

    /**
     * Internal Path->File cache map
     *
     * Caches the files, so they remain flock()ed
     *
     * Could be optimized for a threadsafe HashMap
     */
    entries: Arc<RwLock<HashMap<StoreId, StoreEntry>>>,
}

impl Store {
    /// Creates the Entry at the given location (inside the entry)
    pub fn create(&self, entry: Entry) -> Result<()> {
        unimplemented!();
    }

    /// Borrow a given Entry. When the `FileLockEntry` is either `update`d or
    /// dropped, the new Entry is written to disk
    pub fn retrieve<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> {
        unimplemented!();
    }

    /// Return the `FileLockEntry` and write to disk
    pub fn update<'a>(&'a self, entry: FileLockEntry<'a>) -> Result<()> {
        unimplemented!();
    }

    /// Retrieve a copy of a given entry, this cannot be used to mutate
    /// the one on disk
    pub fn retrieve_copy(&self, id: StoreId) -> Result<Entry> {
        unimplemented!();
    }

    /// Delete an entry
    pub fn delete(&self, id: StoreId) -> Result<()> {
        unimplemented!();
    }
}

impl Drop for Store {

    /**
     * Unlock all files on drop
     *
     * TODO: Error message when file cannot be unlocked?
     */
    fn drop(&mut self) {
        self.entries.write().unwrap()
            .iter().map(|f| f.1.file.unlock());
    }

}

/// A struct that allows you to borrow an Entry
pub struct FileLockEntry<'a> {
    store: &'a Store,
    entry: Entry,
    key: StoreId,
}

impl<'a> FileLockEntry<'a, > {
    fn new(store: &'a Store, entry: Entry, key: StoreId) -> FileLockEntry<'a> {
        FileLockEntry {
            store: store,
            entry: entry,
            key: key,
        }
    }
}

impl<'a> ::std::ops::Deref for FileLockEntry<'a> {
    type Target = Entry;

    fn deref(&self) -> &Self::Target {
        &self.entry
    }
}

impl<'a> ::std::ops::DerefMut for FileLockEntry<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.entry
    }
}

impl<'a> Drop for FileLockEntry<'a> {
    fn drop(&mut self) {
        let mut map = self.store.entries.write().unwrap();
        map.get_mut(&self.key).unwrap().set_entry(self.entry.clone());
    }
}

#[cfg(test)]
mod test {
    use std::path::PathBuf;
    use store::{StoreId, IntoStoreId};

    #[test]
    fn into_storeid_trait() {
        let buf = PathBuf::from("abc/def");

        let test = ("abc", "def");
        assert_eq!(buf, test.into_storeid());

        let test = "abc/def";
        assert_eq!(buf, test.into_storeid());

        let test = String::from("abc/def");
        assert_eq!(buf, test.into_storeid());

        let test = PathBuf::from("abc/def");
        assert_eq!(buf, test.into_storeid());
    }
}

<|endoftext|>


<commit_before>#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
#![feature(box_syntax)]
#![feature(libc)]
#![feature(io)]
#![feature(core)]
#![feature(collections)]
#[macro_use]
#[link]
extern crate log;
#[macro_use]
extern crate bitflags;
extern crate serialize;

pub mod config;
pub mod core;
pub mod handlers;
pub mod layout;
pub mod util;
pub mod window_manager;
pub mod window_system;
<commit_msg>removed old orphan check<commit_after>#![feature(unboxed_closures)]
#![feature(box_syntax)]
#![feature(libc)]
#![feature(io)]
#![feature(core)]
#![feature(collections)]
#[macro_use]
#[link]
extern crate log;
#[macro_use]
extern crate bitflags;
extern crate serialize;

pub mod config;
pub mod core;
pub mod handlers;
pub mod layout;
pub mod util;
pub mod window_manager;
pub mod window_system;
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

/*!
Default configuration for mbed board: http://mbed.org/platforms/mbed-LPC1768

This configuraiton is clocked at 100MHz with Timer1 calibrated for 1us ticks.
It also provides GPIOConfs for all four leds found on the board.
*/

use hal::lpc17xx::init::{SysConf, Clock, Main, PLL0};
use hal::gpio::{GPIOConf, Out};
use hal::lpc17xx::pin::map;

pub static configuration: SysConf = SysConf {
  clock: Clock {
    source: Main(12_000_000),
    pll: PLL0 {
      enabled: true,
      m: 50,
      n: 3,
      divisor: 4,
    }
  },
};

pub static led1: GPIOConf = GPIOConf {
  pin: map::port1::pin18::GPIO,
  direction: Out,
};

pub static led2: GPIOConf = GPIOConf {
  pin: map::port1::pin20::GPIO,
  direction: Out,
};

pub static led3: GPIOConf = GPIOConf {
  pin: map::port1::pin21::GPIO,
  direction: Out,
};

pub static led4: GPIOConf = GPIOConf {
  pin: map::port1::pin23::GPIO,
  direction: Out,
};
<commit_msg>Added pin names for mbed board<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

/*!
Default configuration for mbed board: http://mbed.org/platforms/mbed-LPC1768

This configuraiton is clocked at 100MHz with Timer1 calibrated for 1us ticks.
It also provides GPIOConfs for all four leds found on the board.
*/

use hal::lpc17xx::init::{SysConf, Clock, Main, PLL0};
use hal::gpio::{GPIOConf, Out};
use hal::lpc17xx::pin::map;

/*
// TODO(farcaller): why can't I re-export those?
pub use pin5  = hal::lpc17xx::pin::map::port0::pin9;
pub use pin6  = hal::lpc17xx::pin::map::port0::pin8;
pub use pin7  = hal::lpc17xx::pin::map::port0::pin7;
pub use pin8  = hal::lpc17xx::pin::map::port0::pin6;
pub use pin9  = hal::lpc17xx::pin::map::port0::pin0;
pub use pin10 = hal::lpc17xx::pin::map::port0::pin1;
pub use pin11 = hal::lpc17xx::pin::map::port0::pin18;
pub use pin12 = hal::lpc17xx::pin::map::port0::pin17;
pub use pin13 = hal::lpc17xx::pin::map::port0::pin15;
pub use pin14 = hal::lpc17xx::pin::map::port0::pin16;
pub use pin15 = hal::lpc17xx::pin::map::port0::pin23;
pub use pin16 = hal::lpc17xx::pin::map::port0::pin24;
pub use pin17 = hal::lpc17xx::pin::map::port0::pin25;
pub use pin18 = hal::lpc17xx::pin::map::port0::pin26;

pub use pin19 = hal::lpc17xx::pin::map::port1::pin30;
pub use pin20 = hal::lpc17xx::pin::map::port1::pin31;

pub use pin21 = hal::lpc17xx::pin::map::port2::pin5;
pub use pin22 = hal::lpc17xx::pin::map::port2::pin4;
pub use pin23 = hal::lpc17xx::pin::map::port2::pin3;
pub use pin24 = hal::lpc17xx::pin::map::port2::pin2;
pub use pin25 = hal::lpc17xx::pin::map::port2::pin1;
pub use pin26 = hal::lpc17xx::pin::map::port2::pin0;

pub use pin27 = hal::lpc17xx::pin::map::port0::pin11;
pub use pin28 = hal::lpc17xx::pin::map::port0::pin10;
pub use pin29 = hal::lpc17xx::pin::map::port0::pin5;
pub use pin30 = hal::lpc17xx::pin::map::port0::pin4;
*/

pub static configuration: SysConf = SysConf {
  clock: Clock {
    source: Main(12_000_000),
    pll: PLL0 {
      enabled: true,
      m: 50,
      n: 3,
      divisor: 4,
    }
  },
};

pub static led1: GPIOConf = GPIOConf {
  pin: map::port1::pin18::GPIO,
  direction: Out,
};

pub static led2: GPIOConf = GPIOConf {
  pin: map::port1::pin20::GPIO,
  direction: Out,
};

pub static led3: GPIOConf = GPIOConf {
  pin: map::port1::pin21::GPIO,
  direction: Out,
};

pub static led4: GPIOConf = GPIOConf {
  pin: map::port1::pin23::GPIO,
  direction: Out,
};
<|endoftext|>


<commit_before>use crate::analysis::{
    functions::Info,
    special_functions::{Infos, Type},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    type_name: &str,
    functions: &[Info],
    specials: &Infos,
    trait_name: Option<&str>,
) -> Result<()> {
    for (type_, name) in specials.iter() {
        if let Some(info) = lookup(functions, name) {
            match *type_ {
                Type::Compare => {
                    if specials.get(&Type::Equal).is_none() {
                        generate_eq_compare(w, type_name, info, trait_name)?;
                    }
                    generate_ord(w, type_name, info, trait_name)?;
                }
                Type::Equal => {
                    generate_eq(w, type_name, info, trait_name)?;
                }
                Type::ToString => generate_display(w, type_name, info, trait_name)?,
                Type::Hash => generate_hash(w, type_name, info, trait_name)?,
                _ => {}
            }
        }
    }
    Ok(())
}

fn lookup<'a>(functions: &'a [Info], name: &str) -> Option<&'a Info> {
    functions
        .iter()
        .find(|f| f.status.need_generate() && f.glib_name == name)
}

fn generate_call(func_name: &str, args: &[&str], trait_name: Option<&str>) -> String {
    let mut args_string = String::new();
    let in_trait = trait_name.is_some();

    if in_trait {
        args_string.push_str("self");
    }

    if !args.is_empty() {
        if in_trait {
            args_string.push_str(", ");
        }
        args_string.push_str(&args.join(", "));
    }

    if let Some(trait_name) = trait_name {
        format!(
            "{trait_name}::{func_name}({args})",
            trait_name = trait_name,
            func_name = func_name,
            args = args_string
        )
    } else {
        format!(
            "self.{func_name}({args})",
            func_name = func_name,
            args = args_string
        )
    }
}

fn generate_display(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    use crate::analysis::out_parameters::Mode;

    let call = generate_call(&func.name, &[], trait_name);
    let body = if let Mode::Throws(_) = func.outs.mode {
        format!(
            "if let Ok(val) = {} {{
            write!(f, \"{{}}\", val)
        }} else {{
            Err(fmt::Error)
        }}",
            call
        )
    } else {
        format!("write!(f, \"{{}}\", {})", call)
    };

    writeln!(
        w,
        "
impl fmt::Display for {type_name} {{
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{
        {body}
    }}
}}",
        type_name = type_name,
        body = body
    )
}

fn generate_hash(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &[], trait_name);

    writeln!(
        w,
        "
impl hash::Hash for {type_name} {{
    #[inline]
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {{
        hash::Hash::hash(&{call}, state)
    }}
}}",
        type_name = type_name,
        call = call
    )
}

fn generate_eq(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialEq for {type_name} {{
    #[inline]
    fn eq(&self, other: &Self) -> bool {{
        {call}
    }}
}}

impl Eq for {type_name} {{}}",
        type_name = type_name,
        call = call
    )
}

fn generate_eq_compare(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialEq for {type_name} {{
    #[inline]
    fn eq(&self, other: &Self) -> bool {{
        {call} == 0
    }}
}}

impl Eq for {type_name} {{}}",
        type_name = type_name,
        call = call
    )
}

fn generate_ord(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialOrd for {type_name} {{
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {{
        {call}.partial_cmp(&0)
    }}
}}

impl Ord for {type_name} {{
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {{
        {call}.cmp(&0)
    }}
}}",
        type_name = type_name,
        call = call
    )
}
<commit_msg>trait_impls: Use f.write_str in impl ToString<commit_after>use crate::analysis::{
    functions::Info,
    special_functions::{Infos, Type},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    type_name: &str,
    functions: &[Info],
    specials: &Infos,
    trait_name: Option<&str>,
) -> Result<()> {
    for (type_, name) in specials.iter() {
        if let Some(info) = lookup(functions, name) {
            match *type_ {
                Type::Compare => {
                    if specials.get(&Type::Equal).is_none() {
                        generate_eq_compare(w, type_name, info, trait_name)?;
                    }
                    generate_ord(w, type_name, info, trait_name)?;
                }
                Type::Equal => {
                    generate_eq(w, type_name, info, trait_name)?;
                }
                Type::ToString => generate_display(w, type_name, info, trait_name)?,
                Type::Hash => generate_hash(w, type_name, info, trait_name)?,
                _ => {}
            }
        }
    }
    Ok(())
}

fn lookup<'a>(functions: &'a [Info], name: &str) -> Option<&'a Info> {
    functions
        .iter()
        .find(|f| f.status.need_generate() && f.glib_name == name)
}

fn generate_call(func_name: &str, args: &[&str], trait_name: Option<&str>) -> String {
    let mut args_string = String::new();
    let in_trait = trait_name.is_some();

    if in_trait {
        args_string.push_str("self");
    }

    if !args.is_empty() {
        if in_trait {
            args_string.push_str(", ");
        }
        args_string.push_str(&args.join(", "));
    }

    if let Some(trait_name) = trait_name {
        format!(
            "{trait_name}::{func_name}({args})",
            trait_name = trait_name,
            func_name = func_name,
            args = args_string
        )
    } else {
        format!(
            "self.{func_name}({args})",
            func_name = func_name,
            args = args_string
        )
    }
}

fn generate_display(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    use crate::analysis::out_parameters::Mode;

    let call = generate_call(&func.name, &[], trait_name);
    let body = if let Mode::Throws(_) = func.outs.mode {
        format!(
            "if let Ok(val) = {} {{
            write!(f, \"{{}}\", val)
        }} else {{
            Err(fmt::Error)
        }}",
            call
        )
    } else {
        format!("f.write_str(&{})", call)
    };

    writeln!(
        w,
        "
impl fmt::Display for {type_name} {{
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{
        {body}
    }}
}}",
        type_name = type_name,
        body = body
    )
}

fn generate_hash(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &[], trait_name);

    writeln!(
        w,
        "
impl hash::Hash for {type_name} {{
    #[inline]
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {{
        hash::Hash::hash(&{call}, state)
    }}
}}",
        type_name = type_name,
        call = call
    )
}

fn generate_eq(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialEq for {type_name} {{
    #[inline]
    fn eq(&self, other: &Self) -> bool {{
        {call}
    }}
}}

impl Eq for {type_name} {{}}",
        type_name = type_name,
        call = call
    )
}

fn generate_eq_compare(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialEq for {type_name} {{
    #[inline]
    fn eq(&self, other: &Self) -> bool {{
        {call} == 0
    }}
}}

impl Eq for {type_name} {{}}",
        type_name = type_name,
        call = call
    )
}

fn generate_ord(
    w: &mut dyn Write,
    type_name: &str,
    func: &Info,
    trait_name: Option<&str>,
) -> Result<()> {
    let call = generate_call(&func.name, &["other"], trait_name);

    writeln!(
        w,
        "
impl PartialOrd for {type_name} {{
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {{
        {call}.partial_cmp(&0)
    }}
}}

impl Ord for {type_name} {{
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {{
        {call}.cmp(&0)
    }}
}}",
        type_name = type_name,
        call = call
    )
}
<|endoftext|>