<commit_before>#![feature(io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

const MEMSIZE: usize = 4096;

enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(usize),
    In,
    Out,
    Loop(OpStream)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                    }
                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

struct State {
    index: usize,
    memory: [u8; MEMSIZE]
}

impl State {
    fn new() -> State {
        State { index: 0, memory: [0; MEMSIZE] }
    }

    fn peek(&self) -> u8 {
        self.memory[self.index % MEMSIZE]
    }

    fn poke(&mut self, value: u8) {
        self.memory[self.index % MEMSIZE] = value;
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                // XXX: Ugly expression due to lexical scoping of borrow,
                //      cf. https://github.com/rust-lang/rust/issues/6393
                let x = self.peek();
                self.poke(x.wrapping_add(i));
            }
            &Mov(n) => {
                self.index = self.index.wrapping_add(n);
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self.poke(c[0]);
            }
            &Out => {
                io::stdout().write(&vec![self.peek()]).unwrap();
            }
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(1)),
            '-' => Something(Add(-1)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) if c != ']' => true,
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use super::{State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn state_peek() {
        let mut state = State::new();
        state.memory[state.index] = 23;
        assert_eq!(23, state.peek());
        state.index = 5;
        state.memory[state.index] = 42;
        assert_eq!(42, state.peek());
    }

    #[test]
    fn state_poke() {
        let mut state = State::new();
        state.poke(23);
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state.poke(42);
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state.peek());
        state.step(&Add(42));
        assert_eq!(65, state.peek());
        state.step(&Add(-66));
        assert_eq!(-1, state.peek());
    }

    #[test]
    fn state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn state_step_loop() {
        let mut state = State::new();
        state.poke(23);
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state.peek());
    }

    #[test]
    fn opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(1));
        opstream.add(Add(-1));
        opstream.add(Add(-1));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(-1), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }
}
<commit_msg>refactor: rename test functions<commit_after>#![feature(io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

const MEMSIZE: usize = 4096;

enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(usize),
    In,
    Out,
    Loop(OpStream)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                    }
                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

struct State {
    index: usize,
    memory: [u8; MEMSIZE]
}

impl State {
    fn new() -> State {
        State { index: 0, memory: [0; MEMSIZE] }
    }

    fn peek(&self) -> u8 {
        self.memory[self.index % MEMSIZE]
    }

    fn poke(&mut self, value: u8) {
        self.memory[self.index % MEMSIZE] = value;
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                // XXX: Ugly expression due to lexical scoping of borrow,
                //      cf. https://github.com/rust-lang/rust/issues/6393
                let x = self.peek();
                self.poke(x.wrapping_add(i));
            }
            &Mov(n) => {
                self.index = self.index.wrapping_add(n);
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self.poke(c[0]);
            }
            &Out => {
                io::stdout().write(&vec![self.peek()]).unwrap();
            }
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(1)),
            '-' => Something(Add(-1)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) if c != ']' => true,
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use super::{State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_peek() {
        let mut state = State::new();
        state.memory[state.index] = 23;
        assert_eq!(23, state.peek());
        state.index = 5;
        state.memory[state.index] = 42;
        assert_eq!(42, state.peek());
    }

    #[test]
    fn test_state_poke() {
        let mut state = State::new();
        state.poke(23);
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state.poke(42);
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state.peek());
        state.step(&Add(42));
        assert_eq!(65, state.peek());
        state.step(&Add(-66));
        assert_eq!(-1, state.peek());
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state.poke(23);
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state.peek());
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(1));
        opstream.add(Add(-1));
        opstream.add(Add(-1));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(-1), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules, globs, unsafe_destructor)]

extern crate docopt;
extern crate serialize;
extern crate time;

use docopt::Docopt;

use cpu::CPU;
use cpu::Action as A;
use devices::Devices;

mod cpu;
mod devices;

static USAGE: &'static str = "
Usage: ngaro-rs <image>

Options:
    -h, --help      Show this message.
    -v, --version   Display the version.
";

#[deriving(Decodable)]
struct Args {
    arg_image: String,
    flag_help: bool,
    flag_version: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    let mut cpu = CPU::new(&Path::new(&*args.arg_image));
    let mut devices = Devices::new();
    // Can't use a for loop, due to issues with borrowing scope.
    loop {
        if let Some(action) = cpu.next() {
            match action {
                A::Wait => if devices.do_io(&mut cpu) { break; },
                _ => {}
            }
        } else { break; }
    }
}
<commit_msg>Handle --help and --version<commit_after>#![feature(macro_rules, globs, unsafe_destructor)]

extern crate docopt;
extern crate serialize;
extern crate time;

use docopt::Docopt;

use cpu::CPU;
use cpu::Action as A;
use devices::Devices;

mod cpu;
mod devices;

static USAGE: &'static str = "
Usage:
  ngaro-rs <image>
  ngaro-rs -h | --help
  ngaro-rs --version

Options:
    -h, --help      Show this message.
    --version   Display the version.
";

#[deriving(Decodable)]
struct Args {
    arg_image: String,
    flag_help: bool,
    flag_version: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    if args.flag_help {
        println!("{}", USAGE);
        return;
    }

    if args.flag_version {
        println!("ngaro-rs 0.0.1 dev");
        return;
    }

    let mut cpu = CPU::new(&Path::new(&*args.arg_image));
    let mut devices = Devices::new();
    // Can't use a for loop, due to issues with borrowing scope.
    loop {
        if let Some(action) = cpu.next() {
            match action {
                A::Wait => if devices.do_io(&mut cpu) { break; },
                _ => {}
            }
        } else { break; }
    }
}
<|endoftext|>


<commit_before>
#![feature(phase)]

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

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::os;
use std::io::{OTHER_EXECUTE, OTHER_READ,
              GROUP_EXECUTE, GROUP_READ, GROUP_RWX,
              USER_EXECUTE,  USER_RWX, ALL_PERMISSIONS};
use std::io::fs::{File, PathExtensions, mkdir, mkdir_recursive, chmod};
use std::io::process::{Command, InheritFd, ExitStatus, ExitSignal};

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust-pnacl-trans";

pub fn main() {
    let args = os::args();
    if args.len() != 2 { return; }
    let pexe_path = Path::new(args[1].as_slice());
    let pexe_filename = Path::new(pexe_path.filename().unwrap());

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir_recursive(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let mut pexe = File::open(&pexe_path).unwrap();

    let pexe_stat = pexe.stat().unwrap();
    let (cache_dir, perms) = if pexe_stat.perm.contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.perm.contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.perm.contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };

    let pexe_bin = pexe.read_to_end().unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            ExitStatus(0) => {
                chmod(&nexe_path, perms).unwrap();
            }
            ExitStatus(code) | ExitSignal(code) => {
                let mut stderr = ::std::io::stdio::stderr();
                let mut stdout = ::std::io::stdio::stdout();
                (writeln!(&mut stderr, "`{}` failed:", cmd)).unwrap();
                stdout.write(output.output.as_slice()).unwrap();
                stderr.write(output.error.as_slice()).unwrap();
                os::set_exit_status(code);
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string(),
                                //"-a".to_string(),
                                "-B".to_string(),
                                irt_core.display().to_string(),
                                "-l".to_string(), "/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    sel_ldr_args.extend(args.slice_from(2).to_vec().into_iter());

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(InheritFd(libc::STDOUT_FILENO));
    cmd.stderr(InheritFd(libc::STDERR_FILENO));
    debug!("sel_ldr cmd line: `{}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(ExitStatus(status)) => {
                    os::set_exit_status(status);
                }
                Ok(_) => {
                    os::set_exit_status(1);
                }
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<commit_msg>`rust-pnacl-trans` was renamed to `rust_pnacl_trans`.<commit_after>
#![feature(phase)]

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

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::os;
use std::io::{OTHER_EXECUTE, OTHER_READ,
              GROUP_EXECUTE, GROUP_READ, GROUP_RWX,
              USER_EXECUTE,  USER_RWX, ALL_PERMISSIONS};
use std::io::fs::{File, PathExtensions, mkdir, mkdir_recursive, chmod};
use std::io::process::{Command, InheritFd, ExitStatus, ExitSignal};

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust_pnacl_trans";

pub fn main() {
    let args = os::args();
    if args.len() != 2 { return; }
    let pexe_path = Path::new(args[1].as_slice());
    let pexe_filename = Path::new(pexe_path.filename().unwrap());

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir_recursive(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let mut pexe = File::open(&pexe_path).unwrap();

    let pexe_stat = pexe.stat().unwrap();
    let (cache_dir, perms) = if pexe_stat.perm.contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.perm.contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.perm.contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };

    let pexe_bin = pexe.read_to_end().unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            ExitStatus(0) => {
                chmod(&nexe_path, perms).unwrap();
            }
            ExitStatus(code) | ExitSignal(code) => {
                let mut stderr = ::std::io::stdio::stderr();
                let mut stdout = ::std::io::stdio::stdout();
                (writeln!(&mut stderr, "`{}` failed:", cmd)).unwrap();
                stdout.write(output.output.as_slice()).unwrap();
                stderr.write(output.error.as_slice()).unwrap();
                os::set_exit_status(code);
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string(),
                                //"-a".to_string(),
                                "-B".to_string(),
                                irt_core.display().to_string(),
                                "-l".to_string(), "/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    sel_ldr_args.extend(args.slice_from(2).to_vec().into_iter());

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(InheritFd(libc::STDOUT_FILENO));
    cmd.stderr(InheritFd(libc::STDERR_FILENO));
    debug!("sel_ldr cmd line: `{}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(ExitStatus(status)) => {
                    os::set_exit_status(status);
                }
                Ok(_) => {
                    os::set_exit_status(1);
                }
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate rand;

use rand::distributions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key, Mouse};

#[derive(Copy, Clone)]
struct Spot {
    //x: usize,
    //y: usize,
    hidden: bool,
    mine: bool,
    flag: bool,
    n: i8,
}

struct Field {
    width: usize,
    height: usize,
    field: Vec<Vec<Spot>>,
}

impl Field {
    fn new(r: f32, w: usize, h: usize) -> Field {
        //TODO: make it so the field isn't rebuilt
        let bt = Range::new(0.,1.);
        let mut rng = rand::thread_rng();
        let mut field = vec![vec![Spot{hidden:false,mine:false,flag:false,n:0}; w]; h];
        for i in 0..h {
            for j in 0..w {
                if bt.ind_sample(&mut rng) < r {
                    field[i][j] = Spot{hidden: true, mine: true, flag: false, n: 0};
                }else{
                    field[i][j] = Spot{hidden: true, mine: false, flag: false, n: 0};
                }
            }
        }
        Field {width: w, height: h, field: field}
    }

    fn swap_mine(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        self.field[x][y].mine = !f.mine;
    }

    fn show_spot(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        if !f.hidden {
            for i in 0..3{
                for j in 0..3{
                    if i == 0 && j == 0 {continue;}
                    if x+i == 0 || x+i>self.width {continue;}
                    if y+j == 0 || y+j>self.height {continue;}
                    println!("{} {}", x, y);
                    self.show_spot(x+i-1, y+j-1);
                }
            }
        }
        if !f.flag {
            self.field[x][y].hidden = false;
        }
    }

    fn flag_spot(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        if f.hidden {
            self.field[x][y].flag = !f.flag;
        }
    }

    fn count_field(&self, x: usize, y: usize) -> u8 {
        let mut n = 0;
        for i in 0..3 {
            if y+i == 0 || y+i == self.height+1 {continue;}
            for j in 0..3 {
                if i == 1 && j == 1 {continue;}
                if x+j == 0 || x+j == self.width+1 {continue;}
                if self.field[y+i-1][x+j-1].mine {n += 1}
            }
        }
        n
    }
}

struct Screen {
    width: isize,
    height: isize,
    spot_length: usize,
    surface: sdl::video::Surface,
}

impl Screen {
    fn new(w: isize, h: isize, l: usize) -> Screen {
        sdl::init(&[sdl::InitFlag::Video]);
        sdl::wm::set_caption("mines", "mines");

        let s = match sdl::video::set_video_mode(w, h, 32,
                                                 &[SurfaceFlag::HWSurface],
                                                 &[VideoFlag::DoubleBuf]) {
            Ok(s) => s,
            Err(err) => panic!("failed to set video mode: {}", err)
        };
        Screen {width: w, height: h, spot_length: l, surface: s}
    }

    fn draw_square(&self, x: i16, y: i16, w: u16, (r,g,b): (u8, u8, u8)) {
        self.surface.fill_rect(Some(sdl::Rect {x: x, y: y, w: w, h: w}), Color::RGB(r, g, b));
    }

    fn draw_num(&self, n: u8, x: i16, y: i16, size: u16) {
        self.draw_square(x, y, size,
            (255, 255, 255)
        );
        let mut n = n;
        let sub = (size-1) as i16/3;
        let pack = (size as i16-sub*3)as i16/2;
        let color = if n == 1 {
            (100,100,255)
        }else if n == 2 {
            (0,255,0)
        }else if n == 3 {
            (255,0,0)
        }else if n == 4 {
            (0,0,255)
        }else if n == 5 {
            (200,50,0)
        }else if n == 6 {
            (0,255,255)
        }else if n == 7 {
            (0,0,0)
        }else {
            (150,150,150)
        };

        loop {
            if n == 0 {break;}
            else if n == 1{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                break;
            }else if n == 2{
                self.draw_square(x+pack, y+pack, sub as u16-1,  color);
                self.draw_square(sub*2+x+pack, sub*2+y+pack, sub as u16-1, color);
                break;
            }else if n == 3{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 2;
            }else if n == 4{
                self.draw_square(x+pack, sub*2+y+pack, sub as u16-1, color);
                self.draw_square(sub*2+x+pack, y+pack, sub as u16-1, color);
                n = 2;
            }else if n == 5{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 4;
            }else if n == 6{
                self.draw_square(x+pack, sub+y+pack, sub as u16-1, color);
                self.draw_square(sub*2+x+pack, sub+y+pack, sub as u16-1, color);
                n = 4;
            }else if n == 7{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 6;
            }else if n == 8{
                self.draw_square(sub+x+pack, y+pack, sub as u16-1, color);
                self.draw_square(sub+x+pack, sub*2+y+pack, sub as u16-1, color);
                n = 6;
            }
        }
    }
    fn draw_field(&self, length: i16, ref field: &Field) {
        let mut n = 0;
        for ref i in field.field.iter() {
            let mut m = 0;
            for ref sq in i.iter() {
                if sq.hidden {
                    self.draw_square(m*length+1,
                        n*length+1,
                        (length-1) as u16,
                        (180, 180, 180)
                    );
                    if sq.flag {
                        self.draw_square(m*length+4,
                            n*length+4,
                            (length-7) as u16,
                            (255, 0, 0)
                        );
                    }
                }else{
                    if sq.mine {
                        self.draw_square(m*length+1,
                            n*length+1,
                            (length-1) as u16,
                            (0, 0, 0)
                        );
                    }else{
                        self.draw_num(
                            field.count_field(m as usize, n as usize),
                            m as i16*length as i16+1,
                            n as i16*length as i16+1,
                            (length-1) as u16
                        );
                    }
                }
                m += 1;
            }
            n += 1;
        }
    }
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;

    let mut field = Field::new(0.1, WIDTH, HEIGHT);

    let screen = Screen::new((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1, SIZE);

    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(b, down, mx, my) => {
                if down {
                    if b == Mouse::Left {
                        field.show_spot(my as usize/SIZE, mx as usize/SIZE);
                    }
                    else if b == Mouse::Right {
                        field.flag_spot(my as usize/SIZE, mx as usize/SIZE);
                    }
                }
            },
            Event::Key(k, down, _, _) => {
                if down {
                    if k == Key::Escape {
                        break;
                    }
                    if k == Key::R {
                        field = Field::new(0.1, WIDTH, HEIGHT);
                    }
                }
            },
            _ => {}
        }
        screen.draw_field(SIZE as i16, &field);
        screen.surface.flip();
    }

    sdl::quit();
}
<commit_msg>fixed coordinate reversion, plus some half changes<commit_after>extern crate sdl;
extern crate rand;

use rand::distributions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key, Mouse};

#[derive(Copy, Clone)]
struct Spot {
    hidden: bool,
    mine: bool,
    flag: bool,
    n: u8,
}

struct Field {
    width: usize,
    height: usize,
    field: Vec<Vec<Spot>>,
}

impl Field {
    fn new(r: f32, w: usize, h: usize) -> Field {
        let bt = Range::new(0.,1.);
        let mut rng = rand::thread_rng();
        let mut field = Vec::with_capacity(h);
        for i in 0..h {
            field.push(Vec::with_capacity(w));
            for _ in 0..w {
                field[i].push(
                    Spot{hidden: true,
                         mine: bt.ind_sample(&mut rng) < r,
                         flag: false,
                         n: 0}
                );
            }
        }
        let mut f = Field {width: w, height: h, field: field};
        f.count_field();
        f
    }

    fn swap_mine(&mut self, x: usize, y: usize) {
        let f = self.field[y][x];
        self.field[y][x].mine = !f.mine;
    }

    fn show_spot(&mut self, x: usize, y: usize) {
        if x > self.width {return;}
        if y > self.height {return;}
        let f = self.field[y][x];
    if !f.flag {
            self.field[y as usize][x as usize].hidden = false;
        }
    }

    fn flag_spot(&mut self, x: usize, y: usize) {
        let f = self.field[y][x];
        if f.hidden {
            self.field[y][x].flag = !f.flag;
        }
    }

    fn count_field(&mut self) {
        for i in 0..self.width {
            for j in 0..self.height {
                self.field[j][i].n = self.count_neighbors(i, j);
            }
        }
    }

    fn count_neighbors(&self, x: usize, y: usize) -> u8 {
        let mut n = 0;
        for i in 0..3 {
            if x+i == 0 || x+i > self.width {continue;}
            for j in 0..3 {
                if i == 1 && j == 1 {continue;}
                if y+j == 0 || y+j > self.height {continue;}
                if self.field[y+j-1][x+i-1].mine {n += 1}
            }
        }
        n
    }

    fn count_flags(&self, x: usize, y: usize) -> u8 {
        let mut n = 0;
        for i in 0..3 {
            if y+i == 0 || y+i == self.height+1 {continue;}
            for j in 0..3 {
                if i == 1 && j == 1 {continue;}
                if x+j == 0 || x+j == self.width+1 {continue;}
                if self.field[y+i-1][x+j-1].flag {n += 1}
            }
        }
        n
    }
}

struct Screen {
    width: isize,
    height: isize,
    spot_length: u16,
    surface: sdl::video::Surface,
}

impl Screen {
    fn new(w: isize, h: isize, l: u16) -> Screen {
        sdl::init(&[sdl::InitFlag::Video]);
        sdl::wm::set_caption("mines", "mines");

        let s = match sdl::video::set_video_mode(w, h, 32,
                                                 &[SurfaceFlag::HWSurface],
                                                 &[VideoFlag::DoubleBuf]) {
            Ok(s) => s,
            Err(err) => panic!("failed to set video mode: {}", err)
        };
        Screen {width: w, height: h, spot_length: l, surface: s}
    }

    fn draw_square(&self, x: u16, y: u16, w: u16, (r,g,b): (u8, u8, u8)) {
        self.surface.fill_rect(Some(sdl::Rect {x: x as i16, y: y as i16, w: w, h: w}), Color::RGB(r, g, b));
    }

    fn draw_num(&self, n: u8, x: u16, y: u16) {
        self.draw_square(x, y, self.spot_length-1,
            (255, 255, 255)
        );
        let mut n = n;
        let sub = self.spot_length-1/3;
        let pack = self.spot_length-sub*3/2;
        let color = if n == 1 {
            (100,100,255)
        }else if n == 2 {
            (0,255,0)
        }else if n == 3 {
            (255,0,0)
        }else if n == 4 {
            (0,0,255)
        }else if n == 5 {
            (200,50,0)
        }else if n == 6 {
            (0,255,255)
        }else if n == 7 {
            (0,0,0)
        }else {
            (150,150,150)
        };

        loop {
            if n == 0 {break;}
            else if n == 1{
                self.draw_square(sub+x+pack, sub+y+pack, sub-1, color);
                break;
            }else if n == 2{
                self.draw_square(x+pack, y+pack, sub-1,  color);
                self.draw_square(sub*2+x+pack, sub*2+y+pack, sub-1, color);
                break;
            }else if n == 3{
                self.draw_square(sub+x+pack, sub+y+pack, sub-1, color);
                n = 2;
            }else if n == 4{
                self.draw_square(x+pack, sub*2+y+pack, sub-1, color);
                self.draw_square(sub*2+x+pack, y+pack, sub-1, color);
                n = 2;
            }else if n == 5{
                self.draw_square(sub+x+pack, sub+y+pack, sub-1, color);
                n = 4;
            }else if n == 6{
                self.draw_square(x+pack, sub+y+pack, sub-1, color);
                self.draw_square(sub*2+x+pack, sub+y+pack, sub-1, color);
                n = 4;
            }else if n == 7{
                self.draw_square(sub+x+pack, sub+y+pack, sub-1, color);
                n = 6;
            }else if n == 8{
                self.draw_square(sub+x+pack, y+pack, sub-1, color);
                self.draw_square(sub+x+pack, sub*2+y+pack, sub-1, color);
                n = 6;
            }
        }
    }
    fn draw_field(&self, ref field: &Field) {
        let length = self.spot_length;
        let mut n = 0;
        for ref i in field.field.iter() {
            let mut m = 0;
            for ref sq in i.iter() {
                if sq.hidden {
                    self.draw_square(m*length+1,
                        n*length+1,
                        length-1,
                        (180, 180, 180)
                    );
                    if sq.flag {
                        self.draw_square(m*length+4,
                            n*length+4,
                            length-7,
                            (255, 0, 0)
                        );
                    }
                }else{
                    if sq.mine {
                        self.draw_square({println!("asd");m*length+1},
                            n*length+1,
                            length-1,
                            (0, 0, 0)
                        );
                    }else{
                        self.draw_num(
                            sq.n,
                            m*length+1,
                            n*length+1
                        );
                    }
                }
                m += 1;
            }
            n += 1;
        }
    }
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;
    const R: f32 = 0.;

    let mut field = Field::new(R, WIDTH, HEIGHT);

    let screen = Screen::new((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1, SIZE as u16);

    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(b, down, mx, my) => {
                if down {
                    if b == Mouse::Left {
                        field.show_spot(mx as usize/SIZE, my as usize/SIZE);
                    }
                    else if b == Mouse::Right {
                        field.flag_spot(mx as usize/SIZE, my as usize/SIZE);
                    }
                }
            },
            Event::Key(k, down, _, _) => {
                if down {
                    if k == Key::Escape {
                        break;
                    }
                    if k == Key::R {
                        field = Field::new(R, WIDTH, HEIGHT);
                    }
                }
            },
            _ => {}
        }
        screen.draw_field(&field);
        screen.surface.flip();
    }

    sdl::quit();
}
<|endoftext|>


<commit_before>#![feature(io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

const MEMSIZE: usize = 4096;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(usize),
    In,
    Out,
    Loop(OpStream)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov((a + b) % MEMSIZE);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                    }
                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

struct State {
    index: usize,
    memory: [u8; MEMSIZE]
}

impl State {
    fn new() -> State {
        State { index: 0, memory: [0; MEMSIZE] }
    }

    fn peek(&self) -> u8 {
        self.memory[self.index % MEMSIZE]
    }

    fn poke(&mut self, value: u8) {
        self.memory[self.index % MEMSIZE] = value;
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                // XXX: Ugly expression due to lexical scoping of borrow,
                //      cf. https://github.com/rust-lang/rust/issues/6393
                let x = self.peek();
                self.poke(x.wrapping_add(i));
            }
            &Mov(n) => {
                self.index = (self.index + n) % MEMSIZE;
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self.poke(c[0]);
            }
            &Out => {
                io::stdout().write(&vec![self.peek()]).unwrap();
            }
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(MEMSIZE-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{MEMSIZE, parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_peek() {
        let mut state = State::new();
        state.memory[state.index] = 23;
        assert_eq!(23, state.peek());
        state.index = 5;
        state.memory[state.index] = 42;
        assert_eq!(42, state.peek());
    }

    #[test]
    fn test_state_poke() {
        let mut state = State::new();
        state.poke(23);
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state.poke(42);
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state.peek());
        state.step(&Add(42));
        assert_eq!(65, state.peek());
        state.step(&Add(190));
        assert_eq!(255, state.peek());
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(MEMSIZE-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state.poke(23);
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state.peek());
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(MEMSIZE-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<commit_msg>feat: dynamic memory allocation<commit_after>#![feature(collections, io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                    }
                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn peek(&self) -> u8 {
        if self.index >= self.memory.len() {
            0
        } else {
            self.memory[self.index]
        }
    }

    fn poke(&mut self, value: u8) {
        if self.index >= self.memory.len() {
            self.memory.resize(self.index * 2 + 1, 0);
        }
        self.memory[self.index] = value;
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                // XXX: Ugly expression due to lexical scoping of borrow,
                //      cf. https://github.com/rust-lang/rust/issues/6393
                let x = self.peek();
                self.poke(x.wrapping_add(i));
            }
            &Mov(n) => {
                self.index = (self.index as isize + n) as usize;
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self.poke(c[0]);
            }
            &Out => {
                io::stdout().write(&vec![self.peek()]).unwrap();
            }
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_peek() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state.peek());
        state.index = 5;
        assert_eq!(42, state.peek());
    }

    #[test]
    fn test_state_poke() {
        let mut state = State::new();
        state.poke(23);
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state.poke(42);
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state.peek());
        state.step(&Add(42));
        assert_eq!(65, state.peek());
        state.step(&Add(190));
        assert_eq!(255, state.peek());
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state.poke(23);
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state.peek());
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(path)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}

fn print_or_none(s: &str, opt: Option<u32>) {
    print!("{}=", s);
    match opt {
        Some(value) => println!("{}", value),
        None => println!("NONE"),
    }
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));
	// State. TODO: Don't just use a u64.
	//let moved = 0;

    //let mut results: Vec<Output> = Vec::new();

    let mut has_addition = false;
    let mut has_deletion = false;

	//let mut current_hunk: Vec<String> = Vec::new();
	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {
		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("");
        print_or_none("line.old_lineno()", line.old_lineno());
        print_or_none("line.new_lineno()", line.new_lineno());
        println!("line.num_lines()={}",  line.num_lines());
        println!("line.content_offset={}", line.content_offset());
        println!("|line.origin()|=|{}|", line.origin());  // Wrap in |'s to detect space characters.
        print!("line.content()={}", str::from_utf8(line.content()).unwrap());

        println!("delta.nfiles()={}", delta.nfiles());
        println!("delta.status()={:?}", delta.status());    // :? is for debug trait.
        println!("delta.old_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.old_file().id(), delta.old_file().size());
        println!("delta.new_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.new_file().id(), delta.new_file().size());

		match line.origin() {
			// Context
			' ' | '=' => {
                print!("= {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Headers
			'F' | 'H' => {
                print!("F {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Additions
			'+' | '>' => {
				print!("+ {}", str::from_utf8(line.content()).unwrap());
                has_addition = true;
				true
			},
			// Deletions
			'-' | '<' => {
				print!("- {}", str::from_utf8(line.content()).unwrap());
                has_deletion = true;
				true
			},
			// Other (We don't care about these.)
			_         => {
                print!("_ {}", str::from_utf8(line.content()).unwrap());
                true
            }
		}
			// Look at that match statement, what a hunk. So hunky.
			// match maybe_hunk {
			//     Some(hunk) => unimplemented!(),
			//     None => unimplemented!(),
			// }
	});

    println!("\nhas_addition={}, has_deletion={}", has_addition, has_deletion);

   // if has_addition && has_deletion {
/*
        results.push(Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
        });
*/
    //}

    if !has_addition || !has_deletion {
        println!("Does not have addition or deletion.");
        Ok(vec![])  // Return empty vector.
    } else {

	    Ok(vec![Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
	    }])
    }

   // Ok(results)
}

#[derive(Show)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<commit_msg>Make print_or_none() accept generic Options.<commit_after>#![feature(core)]
#![feature(path)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}

fn print_or_none<T: std::fmt::Display> (s: &str, opt: Option<T>) {
    print!("{}=", s);
    match opt {
        Some(value) => println!("{}", value),
        None => println!("NONE"),
    }
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));
	// State. TODO: Don't just use a u64.
	//let moved = 0;

    //let mut results: Vec<Output> = Vec::new();

    let mut has_addition = false;
    let mut has_deletion = false;

	//let mut current_hunk: Vec<String> = Vec::new();
	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {
		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("");
        print_or_none("line.old_lineno()", line.old_lineno());
        print_or_none("line.new_lineno()", line.new_lineno());
        println!("line.num_lines()={}",  line.num_lines());
        println!("line.content_offset={}", line.content_offset());
        println!("|line.origin()|=|{}|", line.origin());  // Wrap in |'s to detect space characters.
        print!("line.content()={}", str::from_utf8(line.content()).unwrap());

        println!("delta.nfiles()={}", delta.nfiles());
        println!("delta.status()={:?}", delta.status());    // :? is for debug trait.
        println!("delta.old_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.old_file().id(), delta.old_file().size());
        println!("delta.new_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.new_file().id(), delta.new_file().size());

		match line.origin() {
			// Context
			' ' | '=' => {
                print!("= {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Headers
			'F' | 'H' => {
                print!("F {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Additions
			'+' | '>' => {
				print!("+ {}", str::from_utf8(line.content()).unwrap());
                has_addition = true;
				true
			},
			// Deletions
			'-' | '<' => {
				print!("- {}", str::from_utf8(line.content()).unwrap());
                has_deletion = true;
				true
			},
			// Other (We don't care about these.)
			_         => {
                print!("_ {}", str::from_utf8(line.content()).unwrap());
                true
            }
		}
			// Look at that match statement, what a hunk. So hunky.
			// match maybe_hunk {
			//     Some(hunk) => unimplemented!(),
			//     None => unimplemented!(),
			// }
	});

    println!("\nhas_addition={}, has_deletion={}", has_addition, has_deletion);

   // if has_addition && has_deletion {
/*
        results.push(Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
        });
*/
    //}

    if !has_addition || !has_deletion {
        println!("Does not have addition or deletion.");
        Ok(vec![])  // Return empty vector.
    } else {

	    Ok(vec![Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
	    }])
    }

   // Ok(results)
}

#[derive(Show)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<|endoftext|>


<commit_before>extern crate gfx_gl as gl;
extern crate camera_controllers;
extern crate collada;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use gfx::traits::*;
use gfx_debug_draw::DebugRenderer;

use gl::Gl;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::WindowSettings;
use piston::event::{
    events,
    RenderEvent,
    ResizeEvent,
};

use vecmath::mat4_id;

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::SkinnedRenderer;
use collada::document::ColladaDocument;

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let window = Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings {
            title: "Animation Viewer".to_string(),
            size: [640, 480],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4
        }
    );

    let device = gfx_device_gl::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut frame = gfx::Frame::new(win_width as u16, win_height as u16);

    let window = Rc::new(RefCell::new(window));

    let clear = gfx::ClearData {
        color: [0.3, 0.3, 0.3, 1.0],
        depth: 1.0,
        stencil: 0
    };

    let mut graphics = device.into_graphics();

    let mut debug_renderer = DebugRenderer::new(*graphics.device.get_capabilities(), &mut graphics.device, [frame.width as u32, frame.height as u32], 64, None, None).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();
    let mut skinned_renderer = SkinnedRenderer::from_collada(&mut graphics, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    Gl::load_with(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut elapsed_time = 0f64;

    for e in events(window) {

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update frame
            frame.width = width as u16;
            frame.height = height as u16;

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        orbit_zoom_camera.event(&e);

        if let Some(args) = e.render_args() {
            graphics.clear(clear, gfx::COLOR | gfx::DEPTH, &frame);

            let camera_view = orbit_zoom_camera.camera(args.ext_dt).orthogonal();

            let camera_projection = model_view_projection(
                model,
                camera_view,
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            debug_renderer.update(&mut graphics.device);
            debug_renderer.render(&mut graphics, &frame, camera_projection);

            elapsed_time = elapsed_time + 0.02f64; // TODO use actual time
            skinned_renderer.render(&mut graphics, &frame, camera_view, camera_projection, elapsed_time as f32);

            graphics.end_frame();
        }
    }
}
<commit_msg>update for WindowSettings changes<commit_after>extern crate gfx_gl as gl;
extern crate camera_controllers;
extern crate collada;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use gfx::traits::*;
use gfx_debug_draw::DebugRenderer;

use gl::Gl;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::WindowSettings;
use piston::event::{
    events,
    RenderEvent,
    ResizeEvent,
};

use vecmath::mat4_id;

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::SkinnedRenderer;
use collada::document::ColladaDocument;

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let window = Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Animation Viewer".to_string(),
            piston::window::Size { width: 640, height: 480 }
        ).exit_on_esc(true)
    );

    let device = gfx_device_gl::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut frame = gfx::Frame::new(win_width as u16, win_height as u16);

    let window = Rc::new(RefCell::new(window));

    let clear = gfx::ClearData {
        color: [0.3, 0.3, 0.3, 1.0],
        depth: 1.0,
        stencil: 0
    };

    let mut graphics = device.into_graphics();

    let mut debug_renderer = DebugRenderer::new(*graphics.device.get_capabilities(), &mut graphics.device, [frame.width as u32, frame.height as u32], 64, None, None).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();
    let mut skinned_renderer = SkinnedRenderer::from_collada(&mut graphics, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    Gl::load_with(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });

    let mut elapsed_time = 0f64;

    for e in events(window) {

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update frame
            frame.width = width as u16;
            frame.height = height as u16;

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        orbit_zoom_camera.event(&e);

        if let Some(args) = e.render_args() {
            graphics.clear(clear, gfx::COLOR | gfx::DEPTH, &frame);

            let camera_view = orbit_zoom_camera.camera(args.ext_dt).orthogonal();

            let camera_projection = model_view_projection(
                model,
                camera_view,
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            debug_renderer.update(&mut graphics.device);
            debug_renderer.render(&mut graphics, &frame, camera_projection);

            elapsed_time = elapsed_time + 0.02f64; // TODO use actual time
            skinned_renderer.render(&mut graphics, &frame, camera_view, camera_projection, elapsed_time as f32);

            graphics.end_frame();
        }
    }
}
<|endoftext|>


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

#[derive(Show, PartialEq)]
struct ValueKnowledge;
#[derive(Show, PartialEq)]
struct CodeReference;

#[derive(PartialEq, Clone, Show)]
enum Type {
	Unknown(u32),
	Record(Option<String>, Vec<Type>),
}

#[derive(Show, PartialEq)]
struct Value {
	typ:  Type,
	value: ValueKnowledge,
	pos: CodeReference
}

#[derive(Show, PartialEq)]
enum Goto {
	Branch(usize, usize, usize),	// discriminator, alt1, alt2
	Goto(u32),
	DeadEnd
}

#[derive(Show, PartialEq)]
enum Operation {
	Variable(String),
	MethodCall(String, Vec<u32>),
	Call(String, Vec<u32>),
	Tuple(Vec<usize>),
	Ref(u32),
	Unpack(u32),
	Write(u32),
	Read(u32, String),	// ref, fieldname (can only be used on ReadMany types)
	Return(u32)
}

#[derive(Show, PartialEq)]
struct BBlock {
	vars: HashMap<String, usize>,
	ops: Vec<(usize, Operation)>,
	goto: Goto
}

#[derive(Show, PartialEq)]
struct Function {
	blocks: Vec<BBlock>,
	values: Vec<Value>,
	type_params: Vec<String>
}

#[derive(Show)]
struct TypeError;

fn infer_forward(func: &mut Function) -> Result<(), TypeError> {
	use Operation::*;
	use Type::*;
	for block in func.blocks.iter() {
		for &(pos, ref op) in block.ops.iter() {
			match op {
				&Tuple(ref content) => {
					func.values[pos].typ = Record(None, match func.values[pos].typ {
						Record(None, ref cont) => content.iter().zip(cont.iter()).map(
							|&: (a, b)| superimpose(b, &func.values[*a].typ).unwrap()
						).collect(),
						Unknown(_) => content.iter().map(
							|&: a| func.values[*a].typ.clone() ).collect(),
						_ => return Err(TypeError)
					});
				}
				&Return(_) => {}
				_ => unimplemented!()
			}
		}
	}
	Ok(())
}

fn superimpose(a: &Type, b: &Type) -> Result<Type, TypeError> {
	use Type::*;
	match (a, b) {
		(&Unknown(_), x) => Ok(x.clone()),
		(x, &Unknown(_)) => Ok(x.clone()),
		_ => if a == b {
			Ok(b.clone())
		} else {
			Err(TypeError)
		}
	}
}

fn infer_backward(func: &mut Function) -> Result<(), TypeError> {
	use Operation::*;
	use Type::*;
	for block in func.blocks.iter() {
		for &(pos, ref op) in block.ops.iter().rev() {
			match op {
				&Tuple(ref content) => {
					let cpy = match func.values[pos].typ {
						Record(None, ref x) => x.clone(),
						_ => panic!()
					};
					for (&idx, typ) in content.iter().zip(cpy.into_iter()) {
						func.types[func.values[idx].typ] = superimpose(&func.values[idx].typ, &typ).unwrap();
					}
				}
				&Return(_) => {}
				_ => unimplemented!()
			}
		}
	}
	Ok(())
}

fn type_inference(mut func: Function) -> Function {
	infer_forward(&mut func).unwrap();
	infer_backward(&mut func).unwrap();
	println!("{:?}", func);
	func
}

#[test]
fn emptyfunc() {
	use Operation::*;
	use Type::*;
	assert_eq!(
	type_inference(Function {
		blocks: vec![ BBlock {
			vars: HashMap::new(),	// no parameters
			ops: vec![ (0, Tuple(Vec::new())),
				(1, Return(0)) ],	// return ()
			goto: Goto::DeadEnd
		} ],
		values: vec![ Value {
			typ: 0,
			value: ValueKnowledge,
			pos: CodeReference
		} ],
		types: vec![ Unknown(1) ],	// unit return value (inferred)
		type_params: Vec::new()
	}), Function { blocks: vec![BBlock { vars: HashMap::new(), ops: vec![(0, Tuple(Vec::new())), (1, Return(0))], goto: Goto::DeadEnd }], values: vec![Value { typ: Record(None, vec![]), value: ValueKnowledge, pos: CodeReference }], type_params: Vec::new() });
}<commit_msg>added drop function test<commit_after>use std::collections::HashMap;

#[derive(Show, PartialEq)]
struct ValueKnowledge;
#[derive(Show, PartialEq)]
struct CodeReference;

#[derive(PartialEq, Clone, Show)]
enum Type {
	Unknown(u32),
	Record(Option<String>, Vec<Type>),
}

#[derive(Show, PartialEq)]
struct Value {
	typ:  Type,
	value: ValueKnowledge,
	pos: CodeReference
}

#[derive(Show, PartialEq)]
enum Goto {
	Branch(usize, usize, usize),	// discriminator, alt1, alt2
	Goto(u32),
	DeadEnd
}

#[derive(Show, PartialEq)]
enum Operation {
	Variable(String),
	MethodCall(String, Vec<u32>),
	Call(String, Vec<u32>),
	Tuple(Vec<usize>),
	Ref(u32),
	Unpack(u32),
	Write(u32),
	Read(u32, String),	// ref, fieldname (can only be used on ReadMany types)
	Return(u32)
}

#[derive(Show, PartialEq)]
struct BBlock {
	vars: HashMap<String, usize>,
	ops: Vec<(usize, Operation)>,
	goto: Goto
}

#[derive(Show, PartialEq)]
struct Function {
	blocks: Vec<BBlock>,
	values: Vec<Value>,
	type_params: Vec<String>
}

#[derive(Show)]
struct TypeError;

fn infer_forward(func: &mut Function) -> Result<(), TypeError> {
	use Operation::*;
	use Type::*;
	for block in func.blocks.iter() {
		for &(pos, ref op) in block.ops.iter() {
			match op {
				&Tuple(ref content) => {
					func.values[pos].typ = Record(None, match func.values[pos].typ {
						Record(None, ref cont) => content.iter().zip(cont.iter()).map(
							|&: (a, b)| superimpose(b, &func.values[*a].typ).unwrap()
						).collect(),
						Unknown(_) => content.iter().map(
							|&: a| func.values[*a].typ.clone() ).collect(),
						_ => return Err(TypeError)
					});
				}
				&Return(_) => {}
				_ => unimplemented!()
			}
		}
	}
	Ok(())
}

fn superimpose(a: &Type, b: &Type) -> Result<Type, TypeError> {
	use Type::*;
	match (a, b) {
		(&Unknown(_), x) => Ok(x.clone()),
		(x, &Unknown(_)) => Ok(x.clone()),
		_ => if a == b {
			Ok(b.clone())
		} else {
			Err(TypeError)
		}
	}
}

fn infer_backward(func: &mut Function) -> Result<(), TypeError> {
	use Operation::*;
	use Type::*;
	for block in func.blocks.iter() {
		for &(pos, ref op) in block.ops.iter().rev() {
			match op {
				&Tuple(ref content) => {
					let cpy = match func.values[pos].typ {
						Record(None, ref x) => x.clone(),
						_ => panic!()
					};
					for (&idx, typ) in content.iter().zip(cpy.into_iter()) {
						func.values[idx].typ = superimpose(&func.values[idx].typ, &typ).unwrap();
					}
				}
				&Return(_) => {}
				_ => unimplemented!()
			}
		}
		// TODO: infer variables across blocks
	}
	Ok(())
}

fn type_inference(mut func: Function) -> Function {
	infer_forward(&mut func).unwrap();
	infer_backward(&mut func).unwrap();
	println!("{:?}", func);
	func
}

// single basic block functions
#[test]
fn emptyfunc() {
	use Operation::*;
	use Type::*;
	assert_eq!(type_inference(Function {
		blocks: vec![ BBlock {
			vars: HashMap::new(),	// no parameters
			ops: vec![ (0, Tuple(Vec::new())),
				(1, Return(0)) ],	// return ()
			goto: Goto::DeadEnd
		} ],
		values: vec![ Value {
			typ: Unknown(1),	// unit return value (inferred)
			value: ValueKnowledge,
			pos: CodeReference
		} ],
		type_params: Vec::new()
	}), Function { blocks: vec![BBlock { vars: HashMap::new(), ops: vec![(0, Tuple(Vec::new())), (1, Return(0))], goto: Goto::DeadEnd }], values: vec![Value { typ: Record(None, vec![]), value: ValueKnowledge, pos: CodeReference }], type_params: Vec::new() });
}

#[test]
fn dropfunc() {
	use Operation::*;
	use Type::*;
	let mut param = HashMap::with_capacity(1);
	param.insert("param".to_string(), 0);
	assert_eq!(type_inference(Function {
		blocks: vec![ BBlock {
			vars: param.clone(),
			ops: vec![ (0, Tuple(Vec::new())),
				(1, Return(0)) ],	// return ()
			goto: Goto::DeadEnd
		} ],
		values: vec![ Value {
			typ: Unknown(2),	// unit return value (inferred)
			value: ValueKnowledge,
			pos: CodeReference
		} ],
		type_params: vec![ "Drop".to_string() ],
	}), Function { blocks: vec![BBlock { vars: param, ops: vec![(0u, Tuple(Vec::new())), (1u, Return(0u32))], goto: DeadEnd }], values: vec![Value { typ: Record(None, Vec::new()), value: ValueKnowledge, pos: CodeReference }], type_params: vec!["Drop"] });
}<|endoftext|>