<commit_before>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};
use std::iter;

use rand::{Closed01, Rng};
use rand::distributions::{IndependentSample, Sample, Gamma, LogNormal, RandSample};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>, usize)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let mut vocab_size = 0;
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);    // We assume one-based indexing
            if vocab_size < index {
                vocab_size = index;
            }
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags, vocab_size))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let closed01 = RandSample::<Closed01<f64>>::new();
        let Closed01(x) = closed01.ind_sample(rng);

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
                break;
            }
        }
        ret
    }
}

#[derive(Clone)]
struct Dirichlet {
    alpha: Vec<f64>,
}

impl Dirichlet {
    fn new(alpha: Vec<f64>) -> Dirichlet {
        Dirichlet {
            alpha: alpha,
        }
    }
}

impl Sample<Vec<f64>> for Dirichlet {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Vec<f64> {
        self.ind_sample(rng)
    }
}

impl IndependentSample<Vec<f64>> for Dirichlet {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Vec<f64> {
        let mut sum = 0.0;
        let mut xs = Vec::new();
        for &a in &self.alpha {
            let gamma = Gamma::new(a, 1.0);
            let y = gamma.ind_sample(rng);
            xs.push(y);
            sum += y;
        }
        for x in xs.iter_mut() {
            *x /= sum;
        }
        xs
    }
}

fn lda(dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, burn_in: usize, num_samples: usize) {
    // Initialization
    let num_topics: usize = alpha.len();
    let vocab_size: usize = beta.len();
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut z_samples: Vec<Vec<Vec<usize>>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        let mut z_samples_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
                let zeros: Vec<usize> = iter::repeat(0).take(num_topics).collect();
                z_samples_d.push(zeros);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        z_samples.push(z_samples_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    let mut rng = rand::thread_rng();
    for s in 0..(burn_in + num_samples) {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                let old_z_di = z[d][i];
                let new_z_di = cat.ind_sample(&mut rng);
                z[d][i] = new_z_di;
                if s >= burn_in {
                    z_samples[d][i][new_z_di] += 1;
                }
                // Update ndk and nkv
                ndk[d][old_z_di] -= 1;
                ndk[d][new_z_di] += 1;
                nkv[old_z_di][v] -= 1;
                nkv[new_z_di][v] += 1;
            }
            // Sample theta_d
            let mut alpha_d: Vec<f64> = Vec::new();
            for k in 0..num_topics {
                alpha_d.push(ndk[d][k] as f64 + alpha[k]);
            }
            let dir = Dirichlet::new(alpha_d);
            theta[d] = dir.ind_sample(&mut rng);
        }
        for k in 0..num_topics {
            // Sample phi_k
            let mut beta_k: Vec<f64> = Vec::new();
            for v in 0..vocab_size {
                beta_k.push(nkv[k][v] as f64 + beta[v]);
            }
            let dir = Dirichlet::new(beta_k);
            phi[k] = dir.ind_sample(&mut rng);
        }
        // Evaluate the log-likelihood value for the current parameters
        let mut log_likelihood = 0.0;
        for k in 0..num_topics {
            for v in 0..vocab_size {
                log_likelihood += nkv[k][v] as f64 * f64::ln(phi[k][v]);
            }
        }
        println!("log_likelihood = {}", log_likelihood);
    }
    for (d, z_samples_d) in z_samples.iter().enumerate() {
        for (i, samples) in z_samples_d.iter().enumerate() {
            let mut sum = 0.0;
            for k in 0..num_topics {
                sum += samples[k] as f64;
            }
            print!("z[{:3}][{:3}] = ", d, i);
            for k in 0..num_topics {
                print!("{:3}:{:.2} ", k, samples[k] as f64 / sum);
            }
            println!("");
        }
    }
}

fn make_dataset(num_docs: usize, vocab_size: usize, num_topics: usize, alpha: Vec<f64>, beta: Vec<f64>) -> Vec<Bag> {
    let mut rng = rand::thread_rng();
    // phi
    let dir_beta = Dirichlet::new(beta);
    let mut phi: Vec<Vec<f64>> = Vec::with_capacity(num_topics);
    for k in 0..num_topics {
        // Sample phi_k
        phi.push(dir_beta.ind_sample(&mut rng));
    }
    // theta, nd, z, w
    let dir_alpha = Dirichlet::new(alpha);
    let lognorm = LogNormal::new(100.0, 30.0);
    let mut theta: Vec<Vec<f64>> = Vec::with_capacity(num_docs);
    let mut nd: Vec<usize> = Vec::with_capacity(num_docs);
    let mut z: Vec<Vec<usize>> = Vec::with_capacity(num_docs);
    let mut w: Vec<Vec<usize>> = Vec::with_capacity(num_docs);
    for d in 0..num_docs {
        theta.push(dir_alpha.ind_sample(&mut rng));
        nd.push(f64::floor(lognorm.ind_sample(&mut rng)) as usize);
        let cat_theta = Categorical::new(theta[d].clone());
        let mut z_d = Vec::with_capacity(nd[d]);
        let mut w_d = Vec::with_capacity(nd[d]);
        for i in 0..nd[d] {
            z_d.push(cat_theta.ind_sample(&mut rng));
            let cat_phi = Categorical::new(phi[z_d[i]].clone());
            w_d.push(cat_phi.ind_sample(&mut rng));
        }
        z.push(z_d);
        w.push(w_d);
    }
    // Make bags
    let mut bags: Vec<Bag> = Vec::new();
    for w_d in w {
        let mut bag: Bag = Bag::new();
        for v in w_d {
            let counter = bag.entry(v).or_insert(0);
            *counter += 1;
        }
        bags.push(bag);
    }
    bags
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset, vocab_size) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    let num_topics = 3;
    let alpha: Vec<f64> = iter::repeat(1.0).take(num_topics).collect();
    let beta: Vec<f64> = iter::repeat(1.0).take(vocab_size).collect();

    lda(dataset, alpha, beta, 1000, 10000);
}
<commit_msg>Make the signature of make_dataset() better<commit_after>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};
use std::iter;

use rand::{Closed01, Rng};
use rand::distributions::{IndependentSample, Sample, Gamma, LogNormal, RandSample};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>, usize)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let mut vocab_size = 0;
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);    // We assume one-based indexing
            if vocab_size < index {
                vocab_size = index;
            }
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags, vocab_size))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let closed01 = RandSample::<Closed01<f64>>::new();
        let Closed01(x) = closed01.ind_sample(rng);

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
                break;
            }
        }
        ret
    }
}

#[derive(Clone)]
struct Dirichlet {
    alpha: Vec<f64>,
}

impl Dirichlet {
    fn new(alpha: Vec<f64>) -> Dirichlet {
        Dirichlet {
            alpha: alpha,
        }
    }
}

impl Sample<Vec<f64>> for Dirichlet {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Vec<f64> {
        self.ind_sample(rng)
    }
}

impl IndependentSample<Vec<f64>> for Dirichlet {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Vec<f64> {
        let mut sum = 0.0;
        let mut xs = Vec::new();
        for &a in &self.alpha {
            let gamma = Gamma::new(a, 1.0);
            let y = gamma.ind_sample(rng);
            xs.push(y);
            sum += y;
        }
        for x in xs.iter_mut() {
            *x /= sum;
        }
        xs
    }
}

fn lda(dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, burn_in: usize, num_samples: usize) {
    // Initialization
    let num_topics: usize = alpha.len();
    let vocab_size: usize = beta.len();
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut z_samples: Vec<Vec<Vec<usize>>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        let mut z_samples_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
                let zeros: Vec<usize> = iter::repeat(0).take(num_topics).collect();
                z_samples_d.push(zeros);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        z_samples.push(z_samples_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    let mut rng = rand::thread_rng();
    for s in 0..(burn_in + num_samples) {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                let old_z_di = z[d][i];
                let new_z_di = cat.ind_sample(&mut rng);
                z[d][i] = new_z_di;
                if s >= burn_in {
                    z_samples[d][i][new_z_di] += 1;
                }
                // Update ndk and nkv
                ndk[d][old_z_di] -= 1;
                ndk[d][new_z_di] += 1;
                nkv[old_z_di][v] -= 1;
                nkv[new_z_di][v] += 1;
            }
            // Sample theta_d
            let mut alpha_d: Vec<f64> = Vec::new();
            for k in 0..num_topics {
                alpha_d.push(ndk[d][k] as f64 + alpha[k]);
            }
            let dir = Dirichlet::new(alpha_d);
            theta[d] = dir.ind_sample(&mut rng);
        }
        for k in 0..num_topics {
            // Sample phi_k
            let mut beta_k: Vec<f64> = Vec::new();
            for v in 0..vocab_size {
                beta_k.push(nkv[k][v] as f64 + beta[v]);
            }
            let dir = Dirichlet::new(beta_k);
            phi[k] = dir.ind_sample(&mut rng);
        }
        // Evaluate the log-likelihood value for the current parameters
        let mut log_likelihood = 0.0;
        for k in 0..num_topics {
            for v in 0..vocab_size {
                log_likelihood += nkv[k][v] as f64 * f64::ln(phi[k][v]);
            }
        }
        println!("log_likelihood = {}", log_likelihood);
    }
    for (d, z_samples_d) in z_samples.iter().enumerate() {
        for (i, samples) in z_samples_d.iter().enumerate() {
            let mut sum = 0.0;
            for k in 0..num_topics {
                sum += samples[k] as f64;
            }
            print!("z[{:3}][{:3}] = ", d, i);
            for k in 0..num_topics {
                print!("{:3}:{:.2} ", k, samples[k] as f64 / sum);
            }
            println!("");
        }
    }
}

fn make_dataset(num_docs: usize, alpha: Vec<f64>, beta: Vec<f64>) -> Vec<Bag> {
    let num_topics: usize = alpha.len();
    let vocab_size: usize = beta.len();
    let mut rng = rand::thread_rng();
    // phi
    let dir_beta = Dirichlet::new(beta);
    let mut phi: Vec<Vec<f64>> = Vec::with_capacity(num_topics);
    for k in 0..num_topics {
        // Sample phi_k
        phi.push(dir_beta.ind_sample(&mut rng));
    }
    // theta, nd, z, w
    let dir_alpha = Dirichlet::new(alpha);
    let lognorm = LogNormal::new(100.0, 30.0);
    let mut theta: Vec<Vec<f64>> = Vec::with_capacity(num_docs);
    let mut nd: Vec<usize> = Vec::with_capacity(num_docs);
    let mut z: Vec<Vec<usize>> = Vec::with_capacity(num_docs);
    let mut w: Vec<Vec<usize>> = Vec::with_capacity(num_docs);
    for d in 0..num_docs {
        theta.push(dir_alpha.ind_sample(&mut rng));
        nd.push(f64::floor(lognorm.ind_sample(&mut rng)) as usize);
        let cat_theta = Categorical::new(theta[d].clone());
        let mut z_d = Vec::with_capacity(nd[d]);
        let mut w_d = Vec::with_capacity(nd[d]);
        for i in 0..nd[d] {
            z_d.push(cat_theta.ind_sample(&mut rng));
            let cat_phi = Categorical::new(phi[z_d[i]].clone());
            w_d.push(cat_phi.ind_sample(&mut rng));
        }
        z.push(z_d);
        w.push(w_d);
    }
    // Make bags
    let mut bags: Vec<Bag> = Vec::new();
    for w_d in w {
        let mut bag: Bag = Bag::new();
        for v in w_d {
            let counter = bag.entry(v).or_insert(0);
            *counter += 1;
        }
        bags.push(bag);
    }
    bags
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset, vocab_size) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    let num_topics = 3;
    let alpha: Vec<f64> = iter::repeat(1.0).take(num_topics).collect();
    let beta: Vec<f64> = iter::repeat(1.0).take(vocab_size).collect();

    lda(dataset, alpha, beta, 1000, 10000);
}
<|endoftext|>


<commit_before>extern crate rust_math_parser;

use std::io;
use std::io::Write;

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("To define a function, simply type FUNC_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
        let mut input: String = String::new();
        print!(">>>> ");
        stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
            panic!(x);
        }
        let mut my_parser: rust_math_parser::parser::Parser = rust_math_parser::parser::Parser::new(input);
        match my_parser.parse() {
            Ok(x) => println!("{}", x),
            Err(msg) => println!("{}", msg)
        }
    }
}<commit_msg>Added ability to nicely quit program<commit_after>extern crate rust_math_parser;

use std::io;
use std::io::Write;

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("To define a function, simply type FUNC_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
        let mut input: String = String::new();
        print!(">>>> ");
        stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
            panic!(x);
        }
        input = strip_white_space(input);
        if input == "quit" {
            println!("Exiting...");
            break;
        }
        let mut my_parser: rust_math_parser::parser::Parser = rust_math_parser::parser::Parser::new(input);
        match my_parser.parse() {
            Ok(x) => println!("{}", x),
            Err(msg) => println!("{}", msg)
        }
    }
}

fn strip_white_space(input: String) -> String {
    input.split_whitespace().collect::<Vec<&str>>().join("")
}<|endoftext|>


<commit_before>mod vm;

fn main(){
	let bytecode = "\x0E\x00\x03\x00\x02\x02\x0A";
	println!("Perin v{}",vm::perin_version());
	println!("Perin VM executes FlopFlip bytecode");

	let mut perin = vm::PerinVM::new();
	perin.interpreter(bytecode);
}
<commit_msg>Using unstable core features<commit_after>#![feature(core)]
mod vm;

fn main(){
	let bytecode = "\x0E\x00\x03\x00\x02\x02\x0A";
	println!("Perin v{}",vm::perin_version());
	println!("Perin VM executes FlopFlip bytecode");

	let mut perin = vm::PerinVM::new();
	perin.interpreter(bytecode);
}
<|endoftext|>


<commit_before>mod game;

use game::*;
use std::time::Instant;

#[allow(unreachable_code)]
fn main()
{
	match 5
	{
		0 => play(),
		1 => test_io(),
		2 => test_minimax(),
		3 => test_random(),
		4 => train(),
		5 => {
				println!("Training:");
				for i in 0..100
				{
					println!("Training {}:", i+1);
					train();
					println!("Test {}:", i+1);
					test();
				}
				println!("Testing:");
				test_io();
			},
		_ => {}
	}
}

#[allow(dead_code)]
fn play()
{
	let num = 6; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::IO;
	let p2 = PlayerType::AIQ;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_io()
{
	let num = 2; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::IO;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_minimax()
{
	let num = 100; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::Minimax;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_random()
{
	let num = 100; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::Random;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn train()
{
	let num = 1_000; //number of games to play
	let gps = 10; //games per side
	let p1 = PlayerType::AIQFixed;
	let p2 = PlayerType::AIQ;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

<commit_msg>code fix<commit_after>mod game;

use game::*;
use std::time::Instant;

#[allow(unreachable_code)]
fn main()
{
	match 5
	{
		0 => play(),
		1 => test_io(),
		2 => test_minimax(),
		3 => test_random(),
		4 => train(),
		5 => {
				println!("Training:");
				for i in 0..100
				{
					println!("Training {}:", i+1);
					train();
					println!("Test {}:", i+1);
					test_minimax();
				}
				println!("Testing:");
				test_io();
			},
		_ => {}
	}
}

#[allow(dead_code)]
fn play()
{
	let num = 6; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::IO;
	let p2 = PlayerType::AIQ;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_io()
{
	let num = 2; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::IO;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_minimax()
{
	let num = 100; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::Minimax;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn test_random()
{
	let num = 100; //number of games to play
	let gps = 1; //games per side
	let p1 = PlayerType::Random;
	let p2 = PlayerType::AIQFixed;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

#[allow(dead_code)]
fn train()
{
	let num = 1_000; //number of games to play
	let gps = 10; //games per side
	let p1 = PlayerType::AIQFixed;
	let p2 = PlayerType::AIQ;

	println!("Player X: {:?}", p1);
	println!("Player O: {:?}", p2);
	println!("Playing {} games..", num);

	let mut game = Game::new();
	game.set_start_player(1);
	game.set_player1(p1);
	game.set_player2(p2);

	let now = Instant::now();
	game.play_many(num, gps);
	let elapsed = now.elapsed();
	let sec = (elapsed.as_secs() as f64) + (elapsed.subsec_nanos() as f64 / 1000_000_000.0);
	println!("Time: {} min {:.3} s", (sec / 60.0).floor(), sec % 60.0);
	println!("");
}

<|endoftext|>


<commit_before>extern crate hkg;
extern crate termion;
extern crate rustc_serialize;
extern crate kuchiki;
extern crate chrono;
extern crate cancellation;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::io::{stdout, stdin, Write};
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use rustc_serialize::json;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use hkg::status::*;
use hkg::model::IconItem;
use hkg::state_manager::*;
use hkg::screen_manager::*;
use hkg::resources::*;
use hkg::web::*;
use hkg::responser::*;

fn main() {

    // Initialize
    log4rs::init_file("config/log4rs.yaml", Default::default()).expect("fail to init log4rs");

    // Clear the screen.
    hkg::screen::common::clear_screen();

    let _stdout = stdout();

    // web background services
    let (tx_req, rx_req) = channel::<ChannelItem>();
    let (tx_res, rx_res) = channel::<ChannelItem>();

    let mut app = {

        let stdout = {
            Box::new(_stdout.lock().into_raw_mode().expect("fail to lock stdout"))
        };

        let icon_collection: Box<Vec<IconItem>> = {
            let icon_manifest_string = hkg::utility::readfile(String::from("data/icon.manifest.json"));
            Box::new(json::decode(&icon_manifest_string).expect("fail to lock stdout"))
        };

        hkg::App {
            builder: hkg::builder::Builder::new(),
            state_manager: StateManager::new(),
            screen_manager: ScreenManager::new(),

            // initialize empty page
            list_topic_items: vec![],
            show_item: hkg::builder::Builder::new().default_show_item(),

            status_bar: hkg::screen::status_bar::StatusBar::new(),
            index: hkg::screen::index::Index::new(),
            show: hkg::screen::show::Show::new(icon_collection),

            image_request_count_lock: Arc::new(Mutex::new(0)),
            tx_req: &tx_req,
            rx_res: &rx_res,

            stdout: stdout
        }
    };

    Requester::new(rx_req, tx_res);

    let respsoner = Responser::new();

    let mut index_control = hkg::control::index::Index::new();
    let mut show_control = hkg::control::show::Show::new();

    // topics request
    let status_message = list_page(&mut app.state_manager, &tx_req);
    app.status_bar.append(&app.screen_manager, &status_message);

    loop {

        respsoner.try_recv(&mut app);

        print_screen(&mut app);

        app.status_bar.print(&app.screen_manager);

        app.stdout.flush().expect("fail to flush the stdout");

        if !app.state_manager.is_web_request() {

            let stdin = stdin();

            for c in stdin.keys() {

                if app.screen_manager.is_width_changed() {
                    hkg::screen::common::clear_screen();
                }

                match app.state_manager.get_state() {
                    Status::Startup => {}
                    Status::List => {
                        match index_control.handle(c.ok().expect("fail to get stdin keys"), &mut app) {
                            Some(i) => if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                    Status::Show => {
                        match show_control.handle(c.ok().expect("fail to get stdin keys"), &mut app) {
                            Some(i) => if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                }

            }
        }
    }
}

fn list_page(state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Index(ChannelIndexItem {}),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.set_web_request(true);    // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn print_screen(app: &mut hkg::App) {
    match app.state_manager.get_state() {
        Status::Startup => {}
        Status::List => {
            app.index.print(&mut app.stdout, &app.list_topic_items);
        }
        Status::Show => {
            app.show.print(&mut app.stdout, &app.show_item);
        }
    }
}
<commit_msg>group print screen related<commit_after>extern crate hkg;
extern crate termion;
extern crate rustc_serialize;
extern crate kuchiki;
extern crate chrono;
extern crate cancellation;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::io::{stdout, stdin, Write};
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use rustc_serialize::json;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use hkg::status::*;
use hkg::model::IconItem;
use hkg::state_manager::*;
use hkg::screen_manager::*;
use hkg::resources::*;
use hkg::web::*;
use hkg::responser::*;

fn main() {

    // Initialize
    log4rs::init_file("config/log4rs.yaml", Default::default()).expect("fail to init log4rs");

    // Clear the screen.
    hkg::screen::common::clear_screen();

    let _stdout = stdout();

    // web background services
    let (tx_req, rx_req) = channel::<ChannelItem>();
    let (tx_res, rx_res) = channel::<ChannelItem>();

    let mut app = {

        let stdout = {
            Box::new(_stdout.lock().into_raw_mode().expect("fail to lock stdout"))
        };

        let icon_collection: Box<Vec<IconItem>> = {
            let icon_manifest_string = hkg::utility::readfile(String::from("data/icon.manifest.json"));
            Box::new(json::decode(&icon_manifest_string).expect("fail to lock stdout"))
        };

        hkg::App {
            builder: hkg::builder::Builder::new(),
            state_manager: StateManager::new(),
            screen_manager: ScreenManager::new(),

            // initialize empty page
            list_topic_items: vec![],
            show_item: hkg::builder::Builder::new().default_show_item(),

            status_bar: hkg::screen::status_bar::StatusBar::new(),
            index: hkg::screen::index::Index::new(),
            show: hkg::screen::show::Show::new(icon_collection),

            image_request_count_lock: Arc::new(Mutex::new(0)),
            tx_req: &tx_req,
            rx_res: &rx_res,

            stdout: stdout
        }
    };

    Requester::new(rx_req, tx_res);

    let respsoner = Responser::new();

    let mut index_control = hkg::control::index::Index::new();
    let mut show_control = hkg::control::show::Show::new();

    // topics request
    let status_message = list_page(&mut app.state_manager, &tx_req);
    app.status_bar.append(&app.screen_manager, &status_message);

    loop {

        respsoner.try_recv(&mut app);

        print_screen(&mut app);

        if !app.state_manager.is_web_request() {

            let stdin = stdin();

            for c in stdin.keys() {

                if app.screen_manager.is_width_changed() {
                    hkg::screen::common::clear_screen();
                }

                match app.state_manager.get_state() {
                    Status::Startup => {}
                    Status::List => {
                        match index_control.handle(c.ok().expect("fail to get stdin keys"), &mut app) {
                            Some(i) => if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                    Status::Show => {
                        match show_control.handle(c.ok().expect("fail to get stdin keys"), &mut app) {
                            Some(i) => if i == 0 { return } else { break },
                            None => {}
                        }
                    }
                }

            }
        }
    }
}

fn list_page(state_manager: &mut StateManager, tx_req: &Sender<ChannelItem>) -> String {

    let ci = ChannelItem {
        extra: ChannelItemType::Index(ChannelIndexItem {}),
        result: String::from(""),
    };

    let status_message = match tx_req.send(ci) {
        Ok(()) => {
            state_manager.set_web_request(true);    // *is_web_requesting = true;
            "SOK".to_string()
        }
        Err(e) => format!("{}:{}", "SFAIL", e).to_string(),
    };

    status_message
}

fn print_screen(app: &mut hkg::App) {
    match app.state_manager.get_state() {
        Status::Startup => {}
        Status::List => {
            app.index.print(&mut app.stdout, &app.list_topic_items);
        }
        Status::Show => {
            app.show.print(&mut app.stdout, &app.show_item);
        }
    }

    app.status_bar.print(&app.screen_manager);

    app.stdout.flush().expect("fail to flush the stdout");
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

const N: usize = 9;

struct SudokuBoard {
    /// Cells are represented by a linear vector of sets.
    /// Each set contains the possible values for a cell.
    /// - If the set for a cell is empty, the board, in its
    ///   current state, is unsolvable.
    /// - If the set is a singleton, we have found the solution
    ///   for the current cell.
    cells: Vec<HashSet<usize>>
}

impl SudokuBoard {
    fn from_str(descr: &str) -> Self {
        let mut v: Vec<HashSet<usize>> = Vec::with_capacity(N*N);
        for c in descr.chars() {
            match c {
                '.' => {
                    v.push((1..N+1).collect());
                }
                '1' ... '9' => {
                    // There ought to be a simpler way to create a singleton set.
                    let n = c.to_digit(10).unwrap() as usize;
                    let s = vec![n].into_iter().collect();
                    v.push(s);
                }
                _ => {
                    panic!("Not a valid string")
                }
            }
        }
        SudokuBoard { cells: v }
    }

    fn is_solved(&self) -> bool {
        self.cells.iter().all(|set| set.len() == 1)
    }

    fn get<'a>(&'a self, row: usize, col: usize) -> &'a HashSet<usize> {
        &self.cells[N*row + col]
    }

    fn candidates_for(&self, row: usize, col: usize) -> HashSet<usize> {
        let mut s = self.get(row, col).clone();

        // Row
        for i in 0..N {
            if i != col {
                let t = self.get(row, i);
                if t.len() == 1 {
                    for x in t {
                        s.remove(x);
                    }
                }
            }
        }

        // Col
        for i in 0..N {
            if i != row {
                let t = self.get(i, col);
                if t.len() == 1 {
                    for x in t {
                        s.remove(x);
                    }
                }
            }
        }

        // Group
        let gx = 3 * (row / 3);
        let gy = 3 * (col / 3);
        for i in gx..gx+3 {
            for j in gy..gy+3 {
                if i != row && j != col {
                    let t = self.get(i, j);
                    if t.len() == 1 {
                        for x in t {
                            s.remove(x);
                        }
                    }
                }
            }
        }

        return s;
    }

}

fn main() {
    let sb = SudokuBoard::from_str(
        "12..............................................................................."
    );

    println!("{:?}", sb.is_solved());
    println!("{:?}", sb.candidates_for(0, 0));
    println!("{:?}", sb.candidates_for(0, 1));
    println!("{:?}", sb.candidates_for(1, 0));
    println!("{:?}", sb.candidates_for(2, 2));
}
<commit_msg>Switch to linear indics everywhere<commit_after>use std::collections::BTreeSet;

const N: usize = 9;

fn row(linear_index: usize) -> usize {
    linear_index / N
}

fn col(linear_index: usize) -> usize {
    linear_index % N
}

struct SudokuBoard {
    /// Cells are represented by a linear vector of sets.
    /// Each set contains the possible values for a cell.
    /// - If the set for a cell is empty, the board, in its
    ///   current state, is unsolvable.
    /// - If the set is a singleton, we have found the solution
    ///   for the current cell.
    cells: Vec<BTreeSet<usize>>
}

impl SudokuBoard {
    fn from_str(descr: &str) -> Self {
        let mut v: Vec<BTreeSet<usize>> = Vec::with_capacity(N*N);
        for c in descr.chars() {
            match c {
                '.' => {
                    v.push((1..N+1).collect());
                }
                '1' ... '9' => {
                    // There ought to be a simpler way to create a singleton set.
                    let n = c.to_digit(10).unwrap() as usize;
                    let s = vec![n].into_iter().collect();
                    v.push(s);
                }
                _ => {
                    panic!("Not a valid string")
                }
            }
        }
        SudokuBoard { cells: v }
    }

    fn is_solved(&self) -> bool {
        self.cells.iter().all(|candidates| candidates.len() == 1)
    }

    fn cell_is_solved(&self, idx: usize) -> bool {
        self.cells[idx].len() == 1
    }

    /// Return the  indices of the neighbors of a cell, i.e.,
    /// the indices of the cells in the same row, same column and same
    /// square group.
    fn neighbors(&self, idx: usize) -> BTreeSet<usize> {
        let mut neighbor_indices = BTreeSet::new();

        // Row & column
        for i in 0..N {
            let row_idx = row(idx) + i;
            if row_idx != idx {
                neighbor_indices.insert(row_idx);
            }

            let col_idx = (N*i) + col(idx);
            if col_idx != idx {
                neighbor_indices.insert(col_idx);
            }
        }

        // Group
        let x = 3 * (row(idx) / 3);
        let y = 3 * (col(idx) / 3);
        for i in x .. x+3 {
            for j in y .. y+3 {
                let group_idx = (N*i) + j;
                if group_idx != idx {
                    neighbor_indices.insert(group_idx);
                }
            }
        }

        neighbor_indices
    }

    /*
    fn update_candidates(&mut self, row: usize, col: usize) {
        if self.cell_is_solved(linear_index(row, col)) {
            return;
        }

        // Put non-candidates in a vector, because we cannot
        // do self.cells[idx].remove(x) since self.cells is
        // already borrowed.
        let mut non_candidates: Vec<usize> = Vec::new();
        for n in self.neighbors(row, col) {
            if self.cell_is_solved(n) {
                for x in self.cells[n].iter() {
                    non_candidates.push(*x);
                }
            }
        }
        let idx = linear_index(row, col);
        for nc in non_candidates {
            self.cells[idx].remove(&nc);
        }
    }
    */
    fn print(&self) {
        for i in 0..N*N {
            if self.cell_is_solved(i) {
                for c in self.cells[i].iter() {
                    print!("{}", c);
                }
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut sb = SudokuBoard::from_str(
        "............942.8.16.....29........89.6.....14..25......4.......2...8.9..5....7.."
    );
}
<|endoftext|>


<commit_before>mod eval;
mod lex;
mod parse;

fn main() {
    let input = " (+ 5 (- (* 2 3 4) (/ 9 3))) ";
    match eval::evaluate(input) {
        Ok(num) => println!("{}", num),
        Err(_) => println!("Error"),
    };
}
<commit_msg>Evaluates arg[1]<commit_after>use std::env;

mod eval;
mod lex;
mod parse;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        println!("Usage: ./arithmetic expression");
        return;
    }

    match eval::evaluate(&args[1]) {
        Ok(num) => println!("{}", num),
        Err(_) => println!("Error"),
    };
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;

use piston::event_loop::Events;
use piston::input::{Event, Input, Button, Key};
use piston::window::WindowSettings;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use graphics::polygon::Polygon;
use graphics::{DrawState, Transformed};

fn main() {
    let opengl = OpenGL::V3_2;

    let window = Window::new(
        WindowSettings::new(
            "vs-game",
            [200, 200],
        )
        .exit_on_esc(true)
    ).unwrap();

    let mut gl = GlGraphics::new(opengl);
    let ds = DrawState::new();

    let poly = Polygon::new([0.0, 0.0, 0.0, 1.0]);
    let points = [
        [50.0, 0.0],
        [0.0, 50.0],
        [50.0, 50.0],
    ];
    let mut x = 0.0;
    let mut y = 0.0;

    for e in window.events() {
        use graphics::clear;
        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

        match e {
            Event::Render(r) => gl.draw(r.viewport(), |c, gl| {
                clear(WHITE, gl);
                poly.draw(&points, &ds, c.transform.trans(x, y), gl)
            }),
            Event::Input(Input::Press(Button::Keyboard(k))) =>
                match k {
                    Key::Up => y -= 1.0,
                    Key::Down => y += 1.0,
                    Key::Left => x -= 1.0,
                    Key::Right => x += 1.0,
                    Key::Q => return,
                    _ => (),
                },
            _ => (),
        }
    }
}
<commit_msg>Added a spaceship struct<commit_after>extern crate piston;
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;

use piston::event_loop::Events;
use piston::input::{Event, Input, Button, Key};
use piston::window::WindowSettings;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use graphics::polygon::Polygon;
use graphics::{DrawState, Transformed};

struct Spaceship {
    x: f64,
    y: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [50.0, 0.0],
    [0.0, 50.0],
    [50.0, 50.0],
];

impl Spaceship {
    fn new() -> Spaceship {
        return Spaceship{x: 0.0, y: 0.0};
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let window = Window::new(
        WindowSettings::new(
            "vs-game",
            [200, 200],
        )
        .exit_on_esc(true)
    ).unwrap();

    let mut gl = GlGraphics::new(opengl);
    let ds = DrawState::new();

    let poly = Polygon::new([0.0, 0.0, 0.0, 1.0]);
    let mut spaceship = Spaceship::new();

    for e in window.events() {
        use graphics::clear;
        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

        match e {
            Event::Render(r) => gl.draw(r.viewport(), |c, gl| {
                clear(WHITE, gl);
                poly.draw(&SPACESHIP_POINTS, &ds, c.transform.trans(spaceship.x, spaceship.y), gl)
            }),
            Event::Input(Input::Press(Button::Keyboard(k))) =>
                match k {
                    Key::Up => spaceship.y -= 1.0,
                    Key::Down => spaceship.y += 1.0,
                    Key::Left => spaceship.x -= 1.0,
                    Key::Right => spaceship.x += 1.0,
                    Key::Q => return,
                    _ => (),
                },
            _ => (),
        }
    }
}
<|endoftext|>


<commit_before>extern crate nourish_bot;

#[macro_use]
extern crate clap;

extern crate chrono;
extern crate dotenv;
extern crate reqwest;
extern crate slack_hook;

use std::env;
use std::io::prelude::*;

use chrono::Local;
use clap::{App, SubCommand, Arg};
use slack_hook::{Slack, PayloadBuilder};

fn main() {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .about(crate_description!())
        .subcommand(SubCommand::with_name("print").about("Print the nourish menu"))
        .subcommand(SubCommand::with_name("post")
                        .about("Post the nourish menu to the given Slack channels")
                        .arg(Arg::with_name("slack-channel")
                                 .required(true)
                                 .multiple(true)
                                 .help("A Slack channel (#food) or username (@anrussell)")))
        .get_matches();

    dotenv::dotenv().ok();

    let url = nourish_bot::url_for_date(&Local::today().naive_local());

    let menu = {
        let mut res = reqwest::get(&url.to_string()).unwrap();

        let mut bytes = vec![];
        res.read_to_end(&mut bytes).unwrap();
        let body = String::from_utf8_lossy(&bytes);

        nourish_bot::parse_menu(&body)
    };

    let markdown = menu.to_markdown()
        .unwrap_or_else(|| r"There is no menu today ¯\_(ツ)_/¯".to_string());

    println!("{}", markdown);

    if let Some("print") = matches.subcommand_name() {
        return;
    }

    let channels = matches
        .values_of("slack-channel")
        .map(Iterator::collect)
        .unwrap_or_else(|| vec![]);

    for channel in &channels {
        let slack = Slack::new(env::var("WEBHOOK_URL")
                                   .expect("WEBHOOK_URL is not set")
                                   .as_str())
                .unwrap();
        let p = PayloadBuilder::new()
            .text(markdown.as_str())
            .channel(*channel)
            .username("nourishbot")
            .icon_emoji(":athena:")
            .build()
            .unwrap();

        match slack.send(&p) {
            Ok(()) => println!("Posted to {}", channel),
            Err(err) => println!("Error posting to {}: {}", channel, err),
        }
    }
}
<commit_msg>use post subcommand matches<commit_after>extern crate nourish_bot;

#[macro_use]
extern crate clap;

extern crate chrono;
extern crate dotenv;
extern crate reqwest;
extern crate slack_hook;

use std::env;
use std::io::prelude::*;

use chrono::Local;
use clap::{App, SubCommand, Arg};
use slack_hook::{Slack, PayloadBuilder};

fn main() {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .about(crate_description!())
        .subcommand(SubCommand::with_name("print").about("Print the nourish menu"))
        .subcommand(SubCommand::with_name("post")
                        .about("Post the nourish menu to the given Slack channels")
                        .arg(Arg::with_name("slack-channel")
                                 .required(true)
                                 .multiple(true)
                                 .help("A Slack channel (#food) or username (@anrussell)")))
        .get_matches();

    dotenv::dotenv().ok();

    let url = nourish_bot::url_for_date(&Local::today().naive_local());

    let menu = {
        let mut res = reqwest::get(&url.to_string()).unwrap();

        let mut bytes = vec![];
        res.read_to_end(&mut bytes).unwrap();
        let body = String::from_utf8_lossy(&bytes);

        nourish_bot::parse_menu(&body)
    };

    let markdown = menu.to_markdown()
        .unwrap_or_else(|| r"There is no menu today ¯\_(ツ)_/¯".to_string());

    println!("{}", markdown);

    if let Some("print") = matches.subcommand_name() {
        return;
    }

    if let Some(sub_matches) = matches.subcommand_matches("post") {
        let channels = sub_matches
            .values_of("slack-channel")
            .map(Iterator::collect)
            .unwrap_or_else(|| vec![]);

        for channel in &channels {
            let slack = Slack::new(env::var("WEBHOOK_URL")
                                       .expect("WEBHOOK_URL is not set")
                                       .as_str())
                    .unwrap();
            let p = PayloadBuilder::new()
                .text(markdown.as_str())
                .channel(*channel)
                .username("nourishbot")
                .icon_emoji(":athena:")
                .build()
                .unwrap();

            match slack.send(&p) {
                Ok(()) => println!("Posted to {}", channel),
                Err(err) => println!("Error posting to {}: {}", channel, err),
            }
        }
    }
}
<|endoftext|>


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

// masks for pulling nibbles out of bytes
const U4_LOW:  u8 = 0b00001111;
const U4_HIGH: u8 = 0b11110000;

/// If the CPU enters the `Halt` state then any additional ticks will result in
/// the program exhibiting undefined behavior.
///
#[deriving(PartialEq,Show)]
enum CpuState {
	Continue,
	Halt,
}

/// The P150 virtual machine
/// Represents all information the CPU needs to continue executing a
/// program stored in its main memory.
struct P150Cpu {
	ip:  u8,
	ir: u16,

	reg: [u8, ..16],
	mem: [u8, ..256],
}

impl P150Cpu {
	/// Initializes the P150 CPU
	///
	/// NOTE: This implementation 0s memory; but this is not guaranteed
	/// by the machine specification.
	///
	/// Programs MUST start at memory address 0x00
	fn new() -> P150Cpu {
		P150Cpu {
			ip:  0x00,
			ir:  0x0000,

			reg: [0u8, ..16],
			mem: [0u8, ..256],
		}
	}

	/// Prints the current machine state to the console window
	/// This includes the IP, IR, and all registers.
	/// (Registers will be formatted as 2s complement numbers.)
	fn dump(&self) {
		println!("IP: 0x{:02X}, IR: 0x{:04X}", self.ip, self.ir);

		println!("---\nRegisters\n---")
		for (addr, cell) in self.reg.iter().enumerate() {
			println!("{:01X}: {}", addr, cell)
		}

	#[cfg(test)]
	fn get_reg(&self) -> &[u8] {
		self.reg
	}

	/// Read an array of instructions into main memory
	/// This reads two bytes at a time from the `memory` array
	/// and loads them into the P150s RAM bank, starting from address 0.
	fn init_mem(&mut self, memory: &[u16]) {
		let mut next_cell = 0x00;

		for op in memory.iter() {
			let byte_1 = (*op >> 8) as u8;
			let byte_2 = *op as u8;

			self.mem[next_cell]     = byte_1;
			self.mem[next_cell + 1] = byte_2;
			next_cell += 2
		}
	}

	/// Runs the entire fetch, execute, decode cycle against the current IP
	fn tick(&mut self) -> CpuState {
		self.fetch();

		// decode
		let op = (self.ir >> 12) as u8;
		match op {
			0x0   => { // ADDB
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);   // first input: lower nibble of first byte
				let rloc_i1 = hi_nibble(self.ir as u8);          // second input: upper nibble of second byte
				let rloc_o0 = lo_nibble(self.ir as u8);          // output: lower nibble of second byte

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] + self.reg[rloc_i1 as uint];
				Continue
			},

			0x3   => { // AND
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] & self.reg[rloc_i1 as uint];
				Continue
			},

			0x4   => { // OR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] | self.reg[rloc_i1 as uint];
				Continue
			},

			0x5   => { // XOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] ^ self.reg[rloc_i1 as uint];
				Continue
			},

			0x6   => { // MLOAD
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_i0 = self.ir as u8;

				self.reg[rloc_o0 as uint] = self.mem[mloc_i0 as uint];
				Continue
			},

			0x7   => { // MSTOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_o0 = self.ir as u8;

				self.mem[mloc_o0 as uint] = self.reg[rloc_i0 as uint];
				Continue
			},

			0x8   => { // RMOV
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_o0 = hi_nibble(self.ir as u8);

				debug!("moving from {:02X} to {:02X}", rloc_i0, rloc_o0)
				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint];
				Continue
			},

			0x9   => { // RSET
				let rloc = lo_nibble((self.ir >> 8) as u8);  // lower nibble of first byte
				let rval = self.ir as u8;                    // value is entire second byte

				self.reg[rloc as uint] = rval;               // store value in register
				Continue
			},

			0xA   => { // JMPEQ
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let next_ip = self.ir as u8;

				if self.reg[rloc_i0 as uint] == self.reg[0] { self.ip = next_ip }
				Continue
			},

			0xB   => { Halt },
			_     => { debug!("halt, cpu on fire: {}", op); Halt },
		}
	}

	/// Load the instruction at `IP` and advance the pointer by two bytes.
	/// The instruction is packed into a single `u16` and stored in the instruction register.
	fn fetch(&mut self) {
		// load PC -> IR
		let byte_1 = self.mem[(self.ip+0) as uint];
		let byte_2 = self.mem[(self.ip+1) as uint];

		self.ir  = (byte_1 as u16 << 8) | (byte_2 as u16);
		self.ip += 2;

		debug!("IR set to 0x{:04X} ({:02X},{:02X})", self.ir, byte_1, byte_2)
	}
}

/// Take the lower nibble of a byte
fn lo_nibble(byte: u8) -> u8 {
	(byte & U4_LOW)
}

/// Take the upper nibble of a byte and shift it
/// towards the least significant bits.
fn hi_nibble(byte: u8) -> u8 {
	(byte & U4_HIGH) >> 4
}

fn main() {
	let mut cpu = P150Cpu::new();
	let program = [0x911E, 0x920C, 0x0123, 0x7340, 0x6040, 0xA310, 0x9500, 0xB000, 0x9501, 0xB000];
	cpu.init_mem(program);

	loop {
		match cpu.tick() {
			Continue => { continue; },
			Halt => { println!("CPU halted."); cpu.dump(); break; },
		}
	}
}

#[test]
fn test_hammer_time() {
	// cpu should stop
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0xB000]);

	assert_eq!(cpu.tick(), Halt)
}

#[test]
fn test_registers() {
	// cpu should set, move registers accordingly
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9110, 0x8130, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x3], 16)
}

#[test]
fn test_memory() {
	// memory sets and memory stores should read back successfully
	// uninitialized registers should not match initialized registers
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9120, 0x9330, 0x7140, 0x6240, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert!(cpu.get_reg()[0x1] == cpu.get_reg()[0x2]);
	assert!(cpu.get_reg()[0x1] != cpu.get_reg()[0x3]);
}

#[test]
fn test_bin() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9121, 0x9222, 0x3123, 0x4124, 0x5125, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert!(cpu.get_reg()[0x3] == (0x21 & 0x22));
	assert!(cpu.get_reg()[0x4] == (0x21 | 0x22));
	assert!(cpu.get_reg()[0x5] == (0x21 ^ 0x22));
}

#[test]
fn test_math() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9120, 0x920A, 0x0123, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x3], cpu.get_reg()[0x1] + cpu.get_reg()[0x2])
}

#[test]
fn test_branch() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9021, 0x9121, 0xA108, 0xB000, 0x922A, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x2], 0x2A)
}

<commit_msg>Dump memory, but only in debug mode.<commit_after>#![feature(phase)]
#[phase(plugin, link)] extern crate log;

// masks for pulling nibbles out of bytes
const U4_LOW:  u8 = 0b00001111;
const U4_HIGH: u8 = 0b11110000;

/// If the CPU enters the `Halt` state then any additional ticks will result in
/// the program exhibiting undefined behavior.
///
#[deriving(PartialEq,Show)]
enum CpuState {
	Continue,
	Halt,
}

/// The P150 virtual machine
/// Represents all information the CPU needs to continue executing a
/// program stored in its main memory.
struct P150Cpu {
	ip:  u8,
	ir: u16,

	reg: [u8, ..16],
	mem: [u8, ..256],
}

impl P150Cpu {
	/// Initializes the P150 CPU
	///
	/// NOTE: This implementation 0s memory; but this is not guaranteed
	/// by the machine specification.
	///
	/// Programs MUST start at memory address 0x00
	fn new() -> P150Cpu {
		P150Cpu {
			ip:  0x00,
			ir:  0x0000,

			reg: [0u8, ..16],
			mem: [0u8, ..256],
		}
	}

	/// Prints the current machine state to the console window
	/// This includes the IP, IR, and all registers.
	/// (Registers will be formatted as 2s complement numbers.)
	fn dump(&self) {
		println!("IP: 0x{:02X}, IR: 0x{:04X}", self.ip, self.ir);

		println!("---\nRegisters\n---")
		for (addr, cell) in self.reg.iter().enumerate() {
			println!("{:01X}: {}", addr, cell)
		}

		println!("---")

		debug!("Memory")
		for (addr, cell) in self.mem.iter().enumerate() {
			debug!("{:02X}: {}", addr, cell)
		}
	}

	#[cfg(test)]
	fn get_reg(&self) -> &[u8] {
		self.reg
	}

	/// Read an array of instructions into main memory
	/// This reads two bytes at a time from the `memory` array
	/// and loads them into the P150s RAM bank, starting from address 0.
	fn init_mem(&mut self, memory: &[u16]) {
		let mut next_cell = 0x00;

		for op in memory.iter() {
			let byte_1 = (*op >> 8) as u8;
			let byte_2 = *op as u8;

			self.mem[next_cell]     = byte_1;
			self.mem[next_cell + 1] = byte_2;
			next_cell += 2
		}
	}

	/// Runs the entire fetch, execute, decode cycle against the current IP
	fn tick(&mut self) -> CpuState {
		self.fetch();

		// decode & execute
		let op = (self.ir >> 12) as u8;
		match op {
			0x0   => { // ADDB
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);   // first input: lower nibble of first byte
				let rloc_i1 = hi_nibble(self.ir as u8);          // second input: upper nibble of second byte
				let rloc_o0 = lo_nibble(self.ir as u8);          // output: lower nibble of second byte

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] + self.reg[rloc_i1 as uint];
				Continue
			},

			0x3   => { // AND
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] & self.reg[rloc_i1 as uint];
				Continue
			},

			0x4   => { // OR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] | self.reg[rloc_i1 as uint];
				Continue
			},

			0x5   => { // XOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i1 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint] ^ self.reg[rloc_i1 as uint];
				Continue
			},

			0x6   => { // MLOAD
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_i0 = self.ir as u8;

				self.reg[rloc_o0 as uint] = self.mem[mloc_i0 as uint];
				Continue
			},

			0x7   => { // MSTOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_o0 = self.ir as u8;

				self.mem[mloc_o0 as uint] = self.reg[rloc_i0 as uint];
				Continue
			},

			0x8   => { // RMOV
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_o0 = hi_nibble(self.ir as u8);

				debug!("moving from {:02X} to {:02X}", rloc_i0, rloc_o0)
				self.reg[rloc_o0 as uint] = self.reg[rloc_i0 as uint];
				Continue
			},

			0x9   => { // RSET
				let rloc = lo_nibble((self.ir >> 8) as u8);  // lower nibble of first byte
				let rval = self.ir as u8;                    // value is entire second byte

				self.reg[rloc as uint] = rval;               // store value in register
				Continue
			},

			0xA   => { // JMPEQ
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let next_ip = self.ir as u8;

				if self.reg[rloc_i0 as uint] == self.reg[0] { self.ip = next_ip }
				Continue
			},

			0xB   => { Halt },
			_     => { debug!("halt, cpu on fire: {}", op); Halt },
		}
	}

	/// Load the instruction at `IP` and advance the pointer by two bytes.
	/// The instruction is packed into a single `u16` and stored in the instruction register.
	fn fetch(&mut self) {
		// load PC -> IR
		let byte_1 = self.mem[(self.ip+0) as uint];
		let byte_2 = self.mem[(self.ip+1) as uint];

		self.ir  = (byte_1 as u16 << 8) | (byte_2 as u16);
		self.ip += 2;

		debug!("IR set to 0x{:04X} ({:02X},{:02X})", self.ir, byte_1, byte_2)
	}
}

/// Take the lower nibble of a byte
fn lo_nibble(byte: u8) -> u8 {
	(byte & U4_LOW)
}

/// Take the upper nibble of a byte and shift it
/// towards the least significant bits.
fn hi_nibble(byte: u8) -> u8 {
	(byte & U4_HIGH) >> 4
}

fn main() {
	let mut cpu = P150Cpu::new();
	let program = [0x911E, 0x920C, 0x0123, 0x7340, 0x6040, 0xA310, 0x9500, 0xB000, 0x9501, 0xB000];
	cpu.init_mem(program);

	loop {
		match cpu.tick() {
			Continue => { continue; },
			Halt => { println!("CPU halted."); cpu.dump(); break; },
		}
	}
}

#[test]
fn test_hammer_time() {
	// cpu should stop
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0xB000]);

	assert_eq!(cpu.tick(), Halt)
}

#[test]
fn test_registers() {
	// cpu should set, move registers accordingly
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9110, 0x8130, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x3], 16)
}

#[test]
fn test_memory() {
	// memory sets and memory stores should read back successfully
	// uninitialized registers should not match initialized registers
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9120, 0x9330, 0x7140, 0x6240, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert!(cpu.get_reg()[0x1] == cpu.get_reg()[0x2]);
	assert!(cpu.get_reg()[0x1] != cpu.get_reg()[0x3]);
}

#[test]
fn test_bin() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9121, 0x9222, 0x3123, 0x4124, 0x5125, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert!(cpu.get_reg()[0x3] == (0x21 & 0x22));
	assert!(cpu.get_reg()[0x4] == (0x21 | 0x22));
	assert!(cpu.get_reg()[0x5] == (0x21 ^ 0x22));
}

#[test]
fn test_math() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9120, 0x920A, 0x0123, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x3], cpu.get_reg()[0x1] + cpu.get_reg()[0x2])
}

#[test]
fn test_branch() {
	let mut cpu = P150Cpu::new();
	cpu.init_mem([0x9021, 0x9121, 0xA108, 0xB000, 0x922A, 0xB000]);

	loop {
		if cpu.tick() == Halt { break; }
	}

	assert_eq!(cpu.get_reg()[0x2], 0x2A)
}

<|endoftext|>


<commit_before>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    path: std::path::PathBuf,

    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        path: std::path::PathBuf,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            path,
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(MAX_TASKS)),
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

// Separated from `checksum_task()` to ensure the `add_permits()` call is
// always hit.
fn checksum_task_impl(path: std::path::PathBuf, sender: tokio::sync::mpsc::Sender<ChecksumResult>) {
    let contents = match std::fs::read(&path).map_err(ZakopaneError::Io) {
        Ok(contents) => contents,
        Err(e) => return checksum_task_send_result(Err(e), sender),
    };
    let checksum = crypto_hash::hex_digest(crypto_hash::Algorithm::SHA256, &contents);
    checksum_task_send_result(Ok(ChecksumWithPath::new(checksum, path)), sender);
}

// Represents a spawned checksum task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    semaphore_clone: std::sync::Arc<tokio::sync::Semaphore>,
) {
    checksum_task_impl(path, sender);

    // See comment in `ChecksumTaskManager::spawn_task()`.
    semaphore_clone.add_permits(1);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            return sums;
        }
    }
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    path: std::path::PathBuf,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(MAX_TASKS);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(path, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(context.path).into_iter();
    for entry in walk_iter.filter_entry(|e| {
        !e.file_name()
            .to_str()
            .map(|path| path.starts_with(".")) // XXX(j39m)
            .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if !path.is_file() {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.acquire().await.unwrap();

            // Icky workaround for not being able to pass `SemaphorePermit`
            // directly into a spawned task. Note that new permits are added
            // later in the checksum task.
            //
            // See also: https://github.com/tokio-rs/tokio/issues/1998
            permit.forget();

            let sender = context.sender.clone();
            let semaphore_clone = context.semaphore.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, semaphore_clone))
                .await
                .unwrap();
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(path: std::path::PathBuf) -> String {
    let (dispatcher_data, join_handle) = spawn_collector(path.clone()).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(path: std::path::PathBuf) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(path))
}
<commit_msg>checksum: Discard `.await` on spawned task<commit_after>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    path: std::path::PathBuf,

    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        path: std::path::PathBuf,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            path,
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(MAX_TASKS)),
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

// Separated from `checksum_task()` to ensure the `add_permits()` call is
// always hit.
fn checksum_task_impl(path: std::path::PathBuf, sender: tokio::sync::mpsc::Sender<ChecksumResult>) {
    let contents = match std::fs::read(&path).map_err(ZakopaneError::Io) {
        Ok(contents) => contents,
        Err(e) => return checksum_task_send_result(Err(e), sender),
    };
    let checksum = crypto_hash::hex_digest(crypto_hash::Algorithm::SHA256, &contents);
    checksum_task_send_result(Ok(ChecksumWithPath::new(checksum, path)), sender);
}

// Represents a spawned checksum task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    semaphore_clone: std::sync::Arc<tokio::sync::Semaphore>,
) {
    checksum_task_impl(path, sender);

    // See comment in `ChecksumTaskManager::spawn_task()`.
    semaphore_clone.add_permits(1);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            return sums;
        }
    }
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    path: std::path::PathBuf,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(MAX_TASKS);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(path, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(context.path).into_iter();
    for entry in walk_iter.filter_entry(|e| {
        !e.file_name()
            .to_str()
            .map(|path| path.starts_with(".")) // XXX(j39m)
            .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if !path.is_file() {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.acquire().await.unwrap();

            // Icky workaround for not being able to pass `SemaphorePermit`
            // directly into a spawned task. Note that new permits are added
            // later in the checksum task.
            //
            // See also: https://github.com/tokio-rs/tokio/issues/1998
            permit.forget();

            let sender = context.sender.clone();
            let semaphore_clone = context.semaphore.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, semaphore_clone));
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(path: std::path::PathBuf) -> String {
    let (dispatcher_data, join_handle) = spawn_collector(path.clone()).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(path: std::path::PathBuf) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(path))
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate clap;

use clap::{App, Arg, SubCommand};

use std::fs::File;
use std::io::Read;

pub mod gameboy;

use gameboy::cartridge::Cartridge;

fn main() {
    let matches = App::new("gameboy-rs")
        .version("0.0.0.1")
        .author("Simon Whitehead")
        .about("A GameBoy and GameBoy Colour emulator written in Rust")
        .arg(Arg::with_name("rom")
            .short("r")
            .long("rom")
            .value_name("ROM_PATH")
            .required(true)
            .help("Path to a Gameboy or Gameboy Color ROM")
            .takes_value(true))
        .get_matches();

    let rom = matches.value_of("rom").unwrap();
    let rom_data = load_rom(rom).unwrap();
    let cart = Cartridge::with_rom(rom_data);
    let mut gameboy = gameboy::GameBoy::new(false, cart);
    println!("Loading game: {}", gameboy.cart_details().game_title);

    'init: loop {
        match gameboy.run() {
            false => break 'init,
            _ => (),
        }
    }
}

fn load_rom(fname: &str) -> std::io::Result<Vec<u8>> {
    let mut file = File::open(fname)?;

    let mut contents = Vec::new();
    file.read_to_end(&mut contents)?;

    Ok(contents)
}
<commit_msg>Add some basic timing for vblank testing<commit_after>extern crate byteorder;
extern crate clap;

use clap::{App, Arg, SubCommand};

use std::fs::File;
use std::io::Read;
use std::time::{Duration, Instant};

pub mod gameboy;

use gameboy::cartridge::Cartridge;

fn main() {
    let matches = App::new("gameboy-rs")
        .version("0.0.0.1")
        .author("Simon Whitehead")
        .about("A GameBoy and GameBoy Colour emulator written in Rust")
        .arg(
            Arg::with_name("rom")
                .short("r")
                .long("rom")
                .value_name("ROM_PATH")
                .required(true)
                .help("Path to a Gameboy or Gameboy Color ROM")
                .takes_value(true),
        )
        .get_matches();

    let rom = matches.value_of("rom").unwrap();
    let rom_data = load_rom(rom).unwrap();
    let cart = Cartridge::with_rom(rom_data);
    let mut gameboy = gameboy::GameBoy::new(false, cart);
    println!("Loading game: {}", gameboy.cart_details().game_title);
    let mut now = Instant::now();

    'init: loop {
        if Instant::now().duration_since(now) > Duration::new(1, 0) {
            println!("1 second has elapsed (STUB HERE FOR V-BLANK DEBUGGING)");
            now = Instant::now();
        }
        match gameboy.run() {
            false => break 'init,
            _ => (),
        }
    }
}

fn load_rom(fname: &str) -> std::io::Result<Vec<u8>> {
    let mut file = File::open(fname)?;

    let mut contents = Vec::new();
    file.read_to_end(&mut contents)?;

    Ok(contents)
}
<|endoftext|>


<commit_before>#![feature(if_let)]
#![feature(phase)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate lines;

use std::os;
use std::io::{File, IoResult, BufferedReader};
use std::io::stdio::{stderr, stdout};

use lines::linemapper;

use buf::MemWriter;

mod buf;

fn main() {
    let args = os::args();
    if args.len() < 2 {
        let _ = write!(stderr(), "usage: {:s} <logfile> [<logfile> ...]\n", args[0]);
        std::os::set_exit_status(1);
        return;
    }
    for arg in args.iter().skip(1) {
        if let Err(e) = process_arg(arg.as_slice()) {
            let _ = write!(stderr(), "{}", e);
            std::os::set_exit_status(1);
            return;
        }
    }
}

#[allow(unused_must_use)]
fn process_arg(arg: &str) -> IoResult<()> {
    let f = try!(File::open(&Path::new(arg)));
    let r = BufferedReader::new(f);

    let entry_start = regex!(r"^\d{4}-");

    let mut block = MemWriter::with_capacity(1024);
    let mut stdout = stdout().unwrap();

    let mut line_no = 0u;
    let mut collecting_block = false;
    try!(linemapper::map_lines(r, |line| {
        line_no += 1;
        if entry_start.is_match(String::from_utf8_lossy(line).as_slice()) {
            if collecting_block {
                block.write_char('\n');
                // ~ abort as soon as possible if the write didn't
                // succeed e.g. broken pipe
                if let Err(e) = stdout.write(block.get_ref()) {
                    write!(stderr(), "{}", e);
                    std::os::set_exit_status(1);
                    return false;
                }
                collecting_block = false;
            }
            block.clear();
        } else {
            collecting_block = true;
        }
        write!(block, "{:7u}  ", line_no);
        block.write(line);
        true
    }));

    Ok(())
}
<commit_msg>Make printing line numbers optional<commit_after>#![feature(if_let)]
#![feature(phase)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate getopts;
extern crate lines;

use std::os;
use std::io::{File, IoResult, BufferedReader};
use std::io::stdio::{stderr, stdout};

use getopts::{getopts, optflag};

use lines::linemapper;

use buf::MemWriter;

mod buf;

struct Config {
    line_numbers: bool,
    args: Vec<String>,
}

impl Config {
    fn from_cmdline(args: Vec<String>) -> Result<Config, String> {
        let opts = [
            optflag("n", "line-numbers", "print line numbers"),
            ];
        let matches = match getopts(args.tail(), opts) {
            Ok(m) => m,
            Err(f) => {
                return Err(format!("{}", f));
            }
        };
        if matches.free.len() < 1 {
            return Err(String::from_str("Usage: [OPTIONS] <logfile> [<logfile> ...]"));
        }
        Ok(Config {
            line_numbers: matches.opt_present("n"),
            args: matches.free,
        })
    }
}

// --------------------------------------------------------------------

fn main() {
    let cfg = match Config::from_cmdline(os::args()) {
        Ok(cfg) => cfg,
        Err(e) => {
            let _ = stderr().write_line(e.as_slice());
            std::os::set_exit_status(1);
            return;
        }
    };
    for arg in cfg.args.iter() {
        if let Err(e) = process_arg(&cfg, arg.as_slice()) {
            let _ = write!(stderr(), "{}", e);
            std::os::set_exit_status(1);
            return;
        }
    }
}

// ~ XXX use linereader api and return the io error instead of
// handling it here in this function
fn process_arg(cfg: &Config, arg: &str) -> IoResult<()> {
    let f = try!(File::open(&Path::new(arg)));
    let r = BufferedReader::new(f);

    let entry_start = regex!(r"^\d{4}-");

    let mut block = MemWriter::with_capacity(1024);
    let mut stdout = stdout().unwrap();

    let mut line_no = 0u;
    let mut collecting_block = false;
    linemapper::map_lines(r, |line| {
        line_no += 1;
        if entry_start.is_match(String::from_utf8_lossy(line).as_slice()) {
            if collecting_block {
                let _ = block.write_char('\n');
                // ~ abort as soon as possible if the write didn't
                // succeed e.g. broken pipe
                if let Err(e) = stdout.write(block.get_ref()) {
                    let _ = write!(stderr(), "{}", e);
                    std::os::set_exit_status(1);
                    return false;
                }
                collecting_block = false;
            }
            block.clear();
        } else {
            collecting_block = true;
        }
        if cfg.line_numbers {
            let _ = write!(block, "{:7u}  ", line_no);
        }
        let _ = block.write(line);
        true
    })
}
<|endoftext|>