<commit_before>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc::{self, sigaction as sigaction_t ,siginfo_t, sigset_t};
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SockFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags HowFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

mod ffi {
    use libc;
    extern {
        pub fn sigwait(set: *const libc::sigset_t, sig: *mut libc::c_int) -> libc::c_int;
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(HowFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: HowFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { ffi::sigwait(&self.sigset as *const sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<sigset_t> for SigSet {
    fn as_ref(&self) -> &sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: sigaction_t
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SockFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<sigaction_t>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<sigaction_t>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const sigaction_t, &mut oldact as *mut sigaction_t);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: HowFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<sigset_t>(),
                                             |s| &s.sigset as *const sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<sigset_t>(),
                                                |os| &mut os.sigset as *mut sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

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

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<commit_msg>Do not import libc structs directly.<commit_after>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SockFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags HowFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

mod ffi {
    use libc;
    extern {
        pub fn sigwait(set: *const libc::sigset_t, sig: *mut libc::c_int) -> libc::c_int;
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: libc::sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(HowFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: HowFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { ffi::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: libc::sigaction
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SockFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: HowFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<libc::sigset_t>(),
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<libc::sigset_t>(),
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

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

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<|endoftext|>


<commit_before>pub type Coordinate = [i32; 2];

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

#[derive(Clone, Debug)]
pub struct Grid {
    cell_size: [::Float; 2],
}

impl Grid {
    pub fn new(size: ::Float) -> Grid {
        Grid {
            cell_size: [size, size],
        }
    }
}

impl ::Grid for Grid {
    type Coordinate = Coordinate;
    type Direction = Direction;

    fn get_cell_center(&self, c: Coordinate) -> ::Point {
        [(c[0] as f32 + 0.5) * self.cell_size[0],
         (c[1] as f32 + 0.5) * self.cell_size[1],
         0.0]
    }

    fn get_coordinate(&self, p: &::Point) -> Coordinate {
        [(p[0] / self.cell_size[0]) as i32,
         (p[1] / self.cell_size[1]) as i32]
    }

    fn get_neighbour(&self, c: Coordinate, d: Direction) -> Coordinate {
        match d {
            Direction::North => [c[0], c[1]+1],
            Direction::East  => [c[0]+1, c[1]],
            Direction::South => [c[0], c[1]-1],
            Direction::West  => [c[0]-1, c[1]],
        }
    }

    fn fold_neighbours<U, F: Fn(U, Coordinate, Direction) -> U>(&self, coord: Coordinate, u: U, fun: F) -> U {
        [Direction::North, Direction::East, Direction::South, Direction::West]
            .iter().fold(u, |u, &d| fun(u, self.get_neighbour(coord, d), d))
    }

    fn fold_in_radius<U, F: Fn(U, Coordinate) -> U>(&self, coord: Coordinate, radius: ::Float, mut u: U, fun: F) -> U {
        let ext_x = (radius / self.cell_size[0]) as i32;
        let ext_y = (radius / self.cell_size[1]) as i32;
        for x in coord[0] - ext_x .. coord[0] + ext_x + 1 {
            for y in coord[1] - ext_y .. coord[1] + ext_y + 1 {
                let dist = self.get_distance(coord, [x, y]);
                if dist <= radius {
                    u = fun(u, [x, y]);
                }
            }
        }
        u
    }
}
<commit_msg>Implemented corners and edges for the Quad grid<commit_after>pub type Coordinate = [i32; 2];

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

#[derive(Clone, Debug)]
pub struct Grid {
    cell_size: [::Float; 2],
}

impl Grid {
    /// Create a new grid.
    pub fn new(size: ::Float) -> Grid {
        Grid {
            cell_size: [size, size],
        }
    }

    /// Get all the corners of a given cell, starting with
    /// North-West and going clockwise
    pub fn get_corners(&self, c: Coordinate) -> [::Point; 4] {
        use ::Grid;
        let ext = [self.cell_size[0] * 0.5, self.cell_size[1] * 0.5];
        let center = self.get_cell_center(c);
        [[center[0]-ext[0], center[1]-ext[1], 0.0],
         [center[0]+ext[0], center[1]-ext[1], 0.0],
         [center[0]+ext[0], center[1]+ext[1], 0.0],
         [center[0]-ext[0], center[1]+ext[1], 0.0]]
    }

    /// Fold all of the edges in the area.
    pub fn fold_edges_in_area<U,
        F: Fn(U, ::Point, ::Point, Coordinate, Direction) -> U
    >(  &self, area: &::Area, u: U, fun: F) -> U
    {
        use ::Grid;
        self.fold_in_area(area, u, |mut u, c| {
            let corners = self.get_corners(c);
            u = fun(u, corners[0], corners[1], c, Direction::North);
            u = fun(u, corners[1], corners[2], c, Direction::East);
            u
        })
    }
}

impl ::Grid for Grid {
    type Coordinate = Coordinate;
    type Direction = Direction;

    fn get_cell_center(&self, c: Coordinate) -> ::Point {
        [(c[0] as f32 + 0.5) * self.cell_size[0],
         (c[1] as f32 + 0.5) * self.cell_size[1],
         0.0]
    }

    fn get_coordinate(&self, p: &::Point) -> Coordinate {
        [(p[0] / self.cell_size[0]) as i32,
         (p[1] / self.cell_size[1]) as i32]
    }

    fn get_neighbour(&self, c: Coordinate, d: Direction) -> Coordinate {
        match d {
            Direction::North => [c[0], c[1]+1],
            Direction::East  => [c[0]+1, c[1]],
            Direction::South => [c[0], c[1]-1],
            Direction::West  => [c[0]-1, c[1]],
        }
    }

    fn get_edge(&self, c: Coordinate, d: Direction) -> [::Point; 2] {
        let corners = self.get_corners(c);
        match d {
            Direction::North => [corners[0], corners[1]],
            Direction::East  => [corners[1], corners[2]],
            Direction::South => [corners[2], corners[3]],
            Direction::West  => [corners[3], corners[0]],
        }
    }

    fn fold_neighbours<U, F: Fn(U, Coordinate, Direction) -> U>(&self, coord: Coordinate, u: U, fun: F) -> U {
        [Direction::North, Direction::East, Direction::South, Direction::West]
            .iter().fold(u, |u, &d| fun(u, self.get_neighbour(coord, d), d))
    }

    fn fold_in_radius<U, F: Fn(U, Coordinate) -> U>(&self, coord: Coordinate, radius: ::Float, mut u: U, fun: F) -> U {
        let ext_x = (radius / self.cell_size[0]) as i32;
        let ext_y = (radius / self.cell_size[1]) as i32;
        for x in coord[0] - ext_x .. coord[0] + ext_x + 1 {
            for y in coord[1] - ext_y .. coord[1] + ext_y + 1 {
                let dist = self.get_distance(coord, [x, y]);
                if dist <= radius {
                    u = fun(u, [x, y]);
                }
            }
        }
        u
    }

    fn fold_in_area<U, F: Fn(U, Coordinate) -> U>(&self, area: &::Area, mut u: U, fun: F) -> U {
        let min_c = self.get_coordinate(&area[0]);
        let max_c = self.get_coordinate(&area[1]);
        for x in min_c[0] .. max_c[0]+1 {
            for y in min_c[1] .. max_c[1] + 1 {
                u = fun(u, [x,y]);
            }
        }
        u
    }
}
<|endoftext|>


<commit_before>//!A raytracer.
#![feature(path, io)]
extern crate image;

use std::old_io::File;
use std::num::Float;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection {
    time: f32,
    normal: Vec3
}

trait Scene {
    fn intersect(&self, ray: Ray3) -> Option<Intersection>;
}

struct Sphere {
    center: Point3,
    radius: f32
}

impl Scene for Sphere {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let normal = ray.start + ray.dir * t1 - self.center;
                Some(Intersection { time: t1, normal: normal })
            } else if t2 > 0. {
                let normal = ray.start + ray.dir * t2 - self.center;
                Some(Intersection { time: t2, normal: normal })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3
}

impl Scene for Plane {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection { time: time, normal: self.normal })
            } else {
                None
            }
        }
    }
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        match self.0.intersect(ray) {
            Some(ai) => {
                match self.1.intersect(ray) {
                    Some(bi) => if ai.time < bi.time {
                        Some(ai)
                    } else {
                        Some(bi)
                    },
                    None => Some(ai)
                }
            },
            None => self.1.intersect(ray)
        }
    }
}

fn main() {
    let scene = (
        (Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35
        }),
        (Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0)
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0)
        })
    );

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = y as f32 * scaley - 2.0;
        let cx = x as f32 * scalex - 2.0;

        let ray = Ray3 {
            start: Point3::new(0., 0., -8.0),
            dir: Vec3::new(cx, cy, 8.0)
        };

        let value: f32 = match scene.intersect(ray) {
            Some(intersection) => {
                let scale = -(intersection.normal.mag2() * ray.dir.mag2()).sqrt();
                intersection.normal.dot(ray.dir) / scale
            },
            None => 0.
        };

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(value*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<commit_msg>Change incorrect, weird shading to a single point light source<commit_after>//!A raytracer.
#![feature(path, io)]
extern crate image;

use std::old_io::File;
use std::num::Float;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection {
    time: f32,
    point: Point3,
    normal: Vec3
}

trait Scene {
    fn intersect(&self, ray: Ray3) -> Option<Intersection>;
}

struct Sphere {
    center: Point3,
    radius: f32
}

impl Scene for Sphere {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal
                })
            } else if t2 > 0. {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3
}

impl Scene for Plane {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal
                })
            } else {
                None
            }
        }
    }
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        match self.0.intersect(ray) {
            Some(ai) => {
                match self.1.intersect(ray) {
                    Some(bi) => if ai.time < bi.time {
                        Some(ai)
                    } else {
                        Some(bi)
                    },
                    None => Some(ai)
                }
            },
            None => self.1.intersect(ray)
        }
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn main() {
    let scene = (
        (Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35
        }),
        (Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0)
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0)
        })
    );
    let light = Point3::new(1.0, -1.5, 0.5);

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let ray = Ray3 {
            start: Point3::new(0., 0., -8.0),
            dir: Vec3::new(cx, cy, 8.0)
        };

        let value: f32 = match scene.intersect(ray) {
            Some(intersection) => {
                let light_dir = light - intersection.point;
                let light_strength = 10.0 / light_dir.mag2();
                let scale = (intersection.normal.mag2() * light_dir.mag2()).sqrt();
                clamp(light_strength * intersection.normal.dot(light_dir) / scale)
            },
            None => 0.
        };

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(value*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<|endoftext|>


<commit_before>/// The Toml Read extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueReadExt<'doc> {

    /// Extension function for reading a value from the current toml::Value document
    /// using a custom seperator
    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>>;

    /// Extension function for reading a value from the current toml::Value document mutably
    /// using a custom seperator
    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>>;

    /// Extension function for reading a value from the current toml::Value document
    fn read(&'doc self, query: &str) -> Result<Option<&'doc Value>> {
        self.read_with_seperator(query, '.')
    }

    /// Extension function for reading a value from the current toml::Value document mutably
    fn read_mut(&'doc mut self, query: &str) -> Result<Option<&'doc mut Value>> {
        self.read_mut_with_seperator(query, '.')
    }

}

impl<'doc> TomlValueReadExt<'doc> for Value {

    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>> {
        use resolver::non_mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>> {
        use resolver::mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

}

pub trait TomlValueReadTypeExt<'doc> : TomlValueReadExt<'doc> {
    fn read_string(&'doc self, query: &str) -> Result<String>;
    fn read_int(&'doc self, query: &str) -> Result<i64>;
    fn read_float(&'doc self, query: &str) -> Result<f64>;
    fn read_bool(&'doc self, query: &str) -> Result<bool>;
}

macro_rules! make_type_getter {
    ($fnname:ident, $rettype:ty, $typename:expr, $matcher:pat => $implementation:expr) => {
        fn $fnname(&'doc self, query: &str) -> Result<$rettype> {
            self.read_with_seperator(query, '.').and_then(|o| match o {
                $matcher => $implementation,
                Some(o)  => Err(ErrorKind::TypeError($typename, ::util::name_of_val(&o)).into()),
                None     => Err(ErrorKind::NotAvailable(String::from(query)).into()),
            })
        }
    };
}

impl<'doc, T> TomlValueReadTypeExt<'doc> for T
    where T: TomlValueReadExt<'doc>
{
    make_type_getter!(read_string, String, "String",
                      Some(&Value::String(ref obj)) => Ok(obj.clone()));

    make_type_getter!(read_int, i64, "Integer",
                      Some(&Value::Integer(obj)) => Ok(obj));

    make_type_getter!(read_float, f64, "Float",
                      Some(&Value::Float(obj)) => Ok(obj));

    make_type_getter!(read_bool, bool, "Boolean",
                      Some(&Value::Boolean(obj)) => Ok(obj));
}

#[cfg(test)]
mod test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_empty() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read_with_seperator(&String::from("a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.[0]"), '.');
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    ///
    ///
    /// Querying without specifying the seperator
    ///
    ///

    #[test]
    fn test_read_empty_without_seperator() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read(&String::from("a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.[0]"));
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

#[cfg(test)]
mod high_level_fn_test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_int(&String::from("table.a"));

        assert!(val.is_ok());
        assert_eq!(val.unwrap(), 1);
    }

}

<commit_msg>Change API: The typed read API still returns Result<Option<_>><commit_after>/// The Toml Read extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueReadExt<'doc> {

    /// Extension function for reading a value from the current toml::Value document
    /// using a custom seperator
    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>>;

    /// Extension function for reading a value from the current toml::Value document mutably
    /// using a custom seperator
    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>>;

    /// Extension function for reading a value from the current toml::Value document
    fn read(&'doc self, query: &str) -> Result<Option<&'doc Value>> {
        self.read_with_seperator(query, '.')
    }

    /// Extension function for reading a value from the current toml::Value document mutably
    fn read_mut(&'doc mut self, query: &str) -> Result<Option<&'doc mut Value>> {
        self.read_mut_with_seperator(query, '.')
    }

}

impl<'doc> TomlValueReadExt<'doc> for Value {

    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>> {
        use resolver::non_mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>> {
        use resolver::mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

}

pub trait TomlValueReadTypeExt<'doc> : TomlValueReadExt<'doc> {
    fn read_string(&'doc self, query: &str) -> Result<Option<String>>;
    fn read_int(&'doc self, query: &str)    -> Result<Option<i64>>;
    fn read_float(&'doc self, query: &str)  -> Result<Option<f64>>;
    fn read_bool(&'doc self, query: &str)   -> Result<Option<bool>>;
}

macro_rules! make_type_getter {
    ($fnname:ident, $rettype:ty, $typename:expr, $matcher:pat => $implementation:expr) => {
        fn $fnname(&'doc self, query: &str) -> Result<Option<$rettype>> {
            self.read_with_seperator(query, '.').and_then(|o| match o {
                $matcher => Ok(Some($implementation)),
                Some(o)  => Err(ErrorKind::TypeError($typename, ::util::name_of_val(&o)).into()),
                None     => Ok(None),
            })
        }
    };
}

impl<'doc, T> TomlValueReadTypeExt<'doc> for T
    where T: TomlValueReadExt<'doc>
{
    make_type_getter!(read_string, String, "String", Some(&Value::String(ref obj)) => obj.clone());
    make_type_getter!(read_int, i64, "Integer", Some(&Value::Integer(obj)) => obj);
    make_type_getter!(read_float, f64, "Float", Some(&Value::Float(obj)) => obj);
    make_type_getter!(read_bool, bool, "Boolean", Some(&Value::Boolean(obj)) => obj);
}

#[cfg(test)]
mod test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_empty() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read_with_seperator(&String::from("a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.[0]"), '.');
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    ///
    ///
    /// Querying without specifying the seperator
    ///
    ///

    #[test]
    fn test_read_empty_without_seperator() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read(&String::from("a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.[0]"));
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

#[cfg(test)]
mod high_level_fn_test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val = toml.read_int("table.a").unwrap();

        assert_eq!(val.unwrap(), 1);
    }

}

<|endoftext|>


<commit_before>use super::interpreter;
use super::parser;
use rustyline::{self, line_buffer};
use std::iter;

pub struct Repl {}

impl Repl {
    pub fn start() {
        let quit = "(quit)";
        let mut rl = rustyline::Editor::<ParensCloser>::new();
        rl.add_history_entry(quit);
        rl.set_completer(Some(ParensCloser{}));

        let mut interpreter = interpreter::Interpreter::new();

        loop {
            let line = rl.readline(">> ");
            let line = if line.is_err() { return } else { line.unwrap() };
            if line == quit { return }
            rl.add_history_entry(&line);

            let parsed = parser::parse(line.as_bytes());
            match parsed {
                Ok(value) => println!("=> {}", interpreter.evaluate(&value)),
                Err(err)  => println!("{}", err),
            }
        }
    }
}

struct ParensCloser {}

impl rustyline::completion::Completer for ParensCloser {
    fn complete(&self, line: &str, _: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let unclosed_parens = line.chars()
        .fold(0, |n, c| if c == '(' { n + 1 } else if c == ')' { n - 1 } else { n });
        let missing_parens: String = iter::repeat(')').take(unclosed_parens).collect();
        Result::Ok((line.len(), vec![missing_parens]))
    }

    fn update(&self, line: &mut line_buffer::LineBuffer, _: usize, elected: &str) {
        let len = line.len();
        line.replace(len, len, elected);
    }}
<commit_msg>add repl autocomplete<commit_after>use rustyline::{self, line_buffer};
use std::iter;
use std::collections::btree_set::BTreeSet;
use std::mem;
use super::interpreter;
use super::parser;
use super::scope::SymbolIterator;

pub struct Repl {}

impl Repl {
    pub fn start() {
        let quit = "(quit)";
        let break_chars: BTreeSet<char> = vec![' ', '('].into_iter().collect();
        let mut rl = rustyline::Editor::<IdentCompleter>::new();
        rl.add_history_entry(quit);

        let mut interpreter = interpreter::Interpreter::new();

        loop {
            let idents = SymbolIterator::new(&interpreter.current_scope)
            .map(|(_, &(ref s, _))| s.clone())
            .collect();

            let completer = IdentCompleter {
                break_chars: &break_chars,
                ident_list: idents
            };

            rl.set_completer(Some(completer));

            let line = rl.readline(">> ");
            let line = if line.is_err() { return } else { line.unwrap() };
            if line == quit { return }
            rl.add_history_entry(&line);

            let parsed = parser::parse(line.as_bytes());
            match parsed {
                Ok(value) => println!("=> {}", interpreter.evaluate(&value)),
                Err(err)  => println!("{}", err),
            }
        }
    }
}

struct ParensCloser {}

impl rustyline::completion::Completer for ParensCloser {
    fn complete(&self, line: &str, _: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let unclosed_parens = line.chars()
        .fold(0, |n, c| if c == '(' { n + 1 } else if c == ')' { n - 1 } else { n });
        let missing_parens: String = iter::repeat(')').take(unclosed_parens).collect();
        Result::Ok((line.len(), vec![missing_parens]))
    }

    fn update(&self, line: &mut line_buffer::LineBuffer, _: usize, elected: &str) {
        let len = line.len();
        line.replace(len, len, elected);
    }
}

struct IdentCompleter<'a> {
    break_chars: &'a BTreeSet<char>,
    ident_list: Vec<String>,
}

impl<'a> rustyline::completion::Completer for IdentCompleter<'a> {
    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, &self.break_chars);
        let matches: Vec<String> = self.ident_list.iter()
        .filter(|&ident| ident.starts_with(word))
        .cloned()
        //.chain(iter::once(close_params(line)))
        .collect();
        Ok((start, matches))
    }
}

fn close_params(line: &str) -> String {
    let unclosed_parens = line.chars()
    .fold(0, |n, c| if c == '(' { n + 1 } else if c == ')' { n - 1 } else { n });
    let missing_parens: String = iter::repeat(')').take(unclosed_parens).collect();
    missing_parens
}
<|endoftext|>


<commit_before>use std::collections::BinaryHeap;
use std::cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering};
use std::sync::{Arc, Mutex, Condvar};
use std::thread::Thread;
use std::thunk::Thunk;
use std::time::Duration;

use time;

enum JobType {
    Once(Thunk),
    FixedRate {
        f: Box<FnMut() + Send>,
        rate: Duration,
    },
}

struct Job {
    type_: JobType,
    time: u64,
}

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

impl Ord for Job {
    fn cmp(&self, other: &Job) -> Ordering {
        // reverse because BinaryHeap's a max heap
        self.time.cmp(&other.time).reverse()
    }
}

impl PartialEq for Job {
    fn eq(&self, other: &Job) -> bool {
        self.time == other.time
    }
}

impl Eq for Job {}

struct InnerPool {
    queue: BinaryHeap<Job>,
    shutdown: bool,
}

struct SharedPool {
    inner: Mutex<InnerPool>,
    cvar: Condvar,
}

impl SharedPool {
    fn run(&self, job: Job) {
        let mut inner = self.inner.lock().unwrap();

        // Calls from the pool itself will never hit this, but calls from workers might
        if inner.shutdown {
            return;
        }

        match inner.queue.peek() {
            None => self.cvar.notify_all(),
            Some(e) if e.time > job.time => self.cvar.notify_all(),
            _ => {}
        };
        inner.queue.push(job);
    }
}

/// A fixed-size thread pool which allows jobs to be scheduled in the future.
///
/// When the pool falls out of scope, all pending tasks will be executed, after
/// which the worker threads will shut down.
pub struct ScheduledTaskPool {
    shared: Arc<SharedPool>,
}

impl Drop for ScheduledTaskPool {
    fn drop(&mut self) {
        self.shared.inner.lock().unwrap().shutdown = true;
        self.shared.cvar.notify_all();
    }
}

impl ScheduledTaskPool {
    /// Creates a new `ScheduledTaskPool` with the specified number of threads.
    ///
    /// # Panics
    ///
    /// Panics if `size` is 0.
    pub fn new(size: usize) -> ScheduledTaskPool {
        assert!(size > 0, "size must be positive");

        let inner = InnerPool {
            queue: BinaryHeap::new(),
            shutdown: false,
        };

        let shared = SharedPool {
            inner: Mutex::new(inner),
            cvar: Condvar::new(),
        };

        let pool = ScheduledTaskPool {
            shared: Arc::new(shared),
        };

        for _ in (0..size) {
            let mut worker = Worker {
                shared: pool.shared.clone(),
            };

            Thread::spawn(move || worker.run());
        }

        pool
    }

    /// Asynchronously executes `job` with no added delay.
    pub fn run<F>(&self, job: F) where F: FnOnce() + Send {
        self.run_after(Duration::zero(), job)
    }

    /// Asynchronously executes `job` after the specified delay.
    pub fn run_after<F>(&self, dur: Duration, job: F) where F: FnOnce() + Send {
        let job = Job {
            type_: JobType::Once(Thunk::new(job)),
            time: (time::precise_time_ns() as i64 + dur.num_nanoseconds().unwrap()) as u64,
        };
        self.shared.run(job)
    }

    /// Asynchronously executes `job` repeatedly at the specified rate.
    ///
    /// If the job panics, it will no longer be executed. When the pool is
    /// destroyed, the job will no longer be rescheduled for execution, but any
    /// pending execution of the job will be handled as a normal job would.
    pub fn run_at_fixed_rate<F>(&self, rate: Duration, f: F) where F: FnMut() + Send {
        let job = Job {
            type_: JobType::FixedRate { f: Box::new(f), rate: rate },
            time: (time::precise_time_ns() as i64 + rate.num_nanoseconds().unwrap()) as u64,
        };
        self.shared.run(job)
    }

    /// Consumes the `ScheduledTaskPool`, canceling any pending jobs.
    ///
    /// Currently running jobs will continue to run to completion.
    pub fn shutdown_now(self) {
        self.shared.inner.lock().unwrap().queue.clear();
    }
}

struct Worker {
    shared: Arc<SharedPool>,
}

impl Drop for Worker {
    fn drop(&mut self) {
        // Start up a new worker if this one's going away due to a panic from a job
        if Thread::panicking() {
            let mut worker = Worker {
                shared: self.shared.clone(),
            };
            Thread::spawn(move || worker.run());
        }
    }
}

impl Worker {
    fn run(&mut self) {
        loop {
            match self.get_job() {
                Some(job) => self.run_job(job),
                None => break,
            }
        }
    }

    fn get_job(&self) -> Option<Job> {
        enum Need {
            Wait,
            WaitTimeout(Duration),
        }

        let mut inner = self.shared.inner.lock().unwrap();
        loop {
            let now = time::precise_time_ns();

            let need = match inner.queue.peek() {
                None if inner.shutdown => return None,
                None => Need::Wait,
                Some(e) if e.time <= now => break,
                Some(e) => Need::WaitTimeout(Duration::nanoseconds(e.time as i64 - now as i64)),
            };

            inner = match need {
                Need::Wait => self.shared.cvar.wait(inner).unwrap(),
                Need::WaitTimeout(t) => self.shared.cvar.wait_timeout(inner, t).unwrap().0,
            };
        }

        Some(inner.queue.pop().unwrap())
    }

    fn run_job(&self, job: Job) {
        match job.type_ {
            JobType::Once(f) => f.invoke(()),
            JobType::FixedRate { mut f, rate } => {
                f();
                let new_job = Job {
                    type_: JobType::FixedRate { f: f, rate: rate },
                    time: (job.time as i64 + rate.num_nanoseconds().unwrap()) as u64,
                };
                self.shared.run(new_job)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::iter::AdditiveIterator;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};
    use std::time::Duration;

    use super::ScheduledTaskPool;

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ScheduledTaskPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in range(0, TEST_TASKS) {
            let tx = tx.clone();
            pool.run(move|| {
                tx.send(1us).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
    }

    #[test]
    #[should_fail(expected = "size must be positive")]
    fn test_zero_tasks_panic() {
        ScheduledTaskPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ScheduledTaskPool::new(TEST_TASKS);

        // Panic all the existing threads.
        let waiter = Arc::new(Barrier::new(TEST_TASKS as usize));
        for _ in range(0, TEST_TASKS) {
            let waiter = waiter.clone();
            pool.run(move || -> () {
                waiter.wait();
                panic!();
            });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        let waiter = Arc::new(Barrier::new(TEST_TASKS as usize));
        for _ in range(0, TEST_TASKS) {
            let tx = tx.clone();
            let waiter = waiter.clone();
            pool.run(move || {
                waiter.wait();
                tx.send(1us).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
    }

    #[test]
    fn test_run_after() {
        let pool = ScheduledTaskPool::new(TEST_TASKS);
        let (tx, rx) = channel();

        let tx1 = tx.clone();
        pool.run_after(Duration::seconds(1), move || tx1.send(1us).unwrap());
        pool.run_after(Duration::milliseconds(500), move || tx.send(2us).unwrap());

        assert_eq!(2, rx.recv().unwrap());
        assert_eq!(1, rx.recv().unwrap());
    }

    #[test]
    fn test_jobs_complete_after_drop() {
        let pool = ScheduledTaskPool::new(TEST_TASKS);
        let (tx, rx) = channel();

        let tx1 = tx.clone();
        pool.run_after(Duration::seconds(1), move || tx1.send(1us).unwrap());
        pool.run_after(Duration::milliseconds(500), move || tx.send(2us).unwrap());

        drop(pool);

        assert_eq!(2, rx.recv().unwrap());
        assert_eq!(1, rx.recv().unwrap());
    }

    #[test]
    fn test_fixed_delay_jobs_stop_after_drop() {
        let pool = Arc::new(ScheduledTaskPool::new(TEST_TASKS));
        let (tx, rx) = channel();
        let (tx2, rx2) = channel();

        let mut pool2 = Some(pool.clone());
        let mut i = 0i32;
        pool.run_at_fixed_rate(Duration::milliseconds(500), move || {
            i += 1;
            tx.send(i).unwrap();
            rx2.recv().unwrap();
            if i == 2 {
                drop(pool2.take().unwrap());
            }
        });
        drop(pool);

        assert_eq!(Ok(1), rx.recv());
        tx2.send(()).unwrap();
        assert_eq!(Ok(2), rx.recv());
        tx2.send(()).unwrap();
        assert!(rx.recv().is_err());
    }
}
<commit_msg>Rename thread pool<commit_after>use std::collections::BinaryHeap;
use std::cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering};
use std::sync::{Arc, Mutex, Condvar};
use std::thread::Thread;
use std::thunk::Thunk;
use std::time::Duration;

use time;

enum JobType {
    Once(Thunk),
    FixedRate {
        f: Box<FnMut() + Send>,
        rate: Duration,
    },
}

struct Job {
    type_: JobType,
    time: u64,
}

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

impl Ord for Job {
    fn cmp(&self, other: &Job) -> Ordering {
        // reverse because BinaryHeap's a max heap
        self.time.cmp(&other.time).reverse()
    }
}

impl PartialEq for Job {
    fn eq(&self, other: &Job) -> bool {
        self.time == other.time
    }
}

impl Eq for Job {}

struct InnerPool {
    queue: BinaryHeap<Job>,
    shutdown: bool,
}

struct SharedPool {
    inner: Mutex<InnerPool>,
    cvar: Condvar,
}

impl SharedPool {
    fn run(&self, job: Job) {
        let mut inner = self.inner.lock().unwrap();

        // Calls from the pool itself will never hit this, but calls from workers might
        if inner.shutdown {
            return;
        }

        match inner.queue.peek() {
            None => self.cvar.notify_all(),
            Some(e) if e.time > job.time => self.cvar.notify_all(),
            _ => {}
        };
        inner.queue.push(job);
    }
}

/// A fixed-size thread pool which allows jobs to be scheduled in the future.
///
/// When the pool falls out of scope, all pending tasks will be executed, after
/// which the worker threads will shut down.
pub struct ScheduledThreadPool {
    shared: Arc<SharedPool>,
}

impl Drop for ScheduledThreadPool {
    fn drop(&mut self) {
        self.shared.inner.lock().unwrap().shutdown = true;
        self.shared.cvar.notify_all();
    }
}

impl ScheduledThreadPool {
    /// Creates a new `ScheduledThreadPool` with the specified number of threads.
    ///
    /// # Panics
    ///
    /// Panics if `size` is 0.
    pub fn new(size: usize) -> ScheduledThreadPool {
        assert!(size > 0, "size must be positive");

        let inner = InnerPool {
            queue: BinaryHeap::new(),
            shutdown: false,
        };

        let shared = SharedPool {
            inner: Mutex::new(inner),
            cvar: Condvar::new(),
        };

        let pool = ScheduledThreadPool {
            shared: Arc::new(shared),
        };

        for _ in (0..size) {
            let mut worker = Worker {
                shared: pool.shared.clone(),
            };

            Thread::spawn(move || worker.run());
        }

        pool
    }

    /// Asynchronously executes `job` with no added delay.
    pub fn run<F>(&self, job: F) where F: FnOnce() + Send {
        self.run_after(Duration::zero(), job)
    }

    /// Asynchronously executes `job` after the specified delay.
    pub fn run_after<F>(&self, dur: Duration, job: F) where F: FnOnce() + Send {
        let job = Job {
            type_: JobType::Once(Thunk::new(job)),
            time: (time::precise_time_ns() as i64 + dur.num_nanoseconds().unwrap()) as u64,
        };
        self.shared.run(job)
    }

    /// Asynchronously executes `job` repeatedly at the specified rate.
    ///
    /// If the job panics, it will no longer be executed. When the pool is
    /// destroyed, the job will no longer be rescheduled for execution, but any
    /// pending execution of the job will be handled as a normal job would.
    pub fn run_at_fixed_rate<F>(&self, rate: Duration, f: F) where F: FnMut() + Send {
        let job = Job {
            type_: JobType::FixedRate { f: Box::new(f), rate: rate },
            time: (time::precise_time_ns() as i64 + rate.num_nanoseconds().unwrap()) as u64,
        };
        self.shared.run(job)
    }

    /// Consumes the `ScheduledThreadPool`, canceling any pending jobs.
    ///
    /// Currently running jobs will continue to run to completion.
    pub fn shutdown_now(self) {
        self.shared.inner.lock().unwrap().queue.clear();
    }
}

struct Worker {
    shared: Arc<SharedPool>,
}

impl Drop for Worker {
    fn drop(&mut self) {
        // Start up a new worker if this one's going away due to a panic from a job
        if Thread::panicking() {
            let mut worker = Worker {
                shared: self.shared.clone(),
            };
            Thread::spawn(move || worker.run());
        }
    }
}

impl Worker {
    fn run(&mut self) {
        loop {
            match self.get_job() {
                Some(job) => self.run_job(job),
                None => break,
            }
        }
    }

    fn get_job(&self) -> Option<Job> {
        enum Need {
            Wait,
            WaitTimeout(Duration),
        }

        let mut inner = self.shared.inner.lock().unwrap();
        loop {
            let now = time::precise_time_ns();

            let need = match inner.queue.peek() {
                None if inner.shutdown => return None,
                None => Need::Wait,
                Some(e) if e.time <= now => break,
                Some(e) => Need::WaitTimeout(Duration::nanoseconds(e.time as i64 - now as i64)),
            };

            inner = match need {
                Need::Wait => self.shared.cvar.wait(inner).unwrap(),
                Need::WaitTimeout(t) => self.shared.cvar.wait_timeout(inner, t).unwrap().0,
            };
        }

        Some(inner.queue.pop().unwrap())
    }

    fn run_job(&self, job: Job) {
        match job.type_ {
            JobType::Once(f) => f.invoke(()),
            JobType::FixedRate { mut f, rate } => {
                f();
                let new_job = Job {
                    type_: JobType::FixedRate { f: f, rate: rate },
                    time: (job.time as i64 + rate.num_nanoseconds().unwrap()) as u64,
                };
                self.shared.run(new_job)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::iter::AdditiveIterator;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};
    use std::time::Duration;

    use super::ScheduledThreadPool;

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ScheduledThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in range(0, TEST_TASKS) {
            let tx = tx.clone();
            pool.run(move|| {
                tx.send(1us).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
    }

    #[test]
    #[should_fail(expected = "size must be positive")]
    fn test_zero_tasks_panic() {
        ScheduledThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ScheduledThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        let waiter = Arc::new(Barrier::new(TEST_TASKS as usize));
        for _ in range(0, TEST_TASKS) {
            let waiter = waiter.clone();
            pool.run(move || -> () {
                waiter.wait();
                panic!();
            });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        let waiter = Arc::new(Barrier::new(TEST_TASKS as usize));
        for _ in range(0, TEST_TASKS) {
            let tx = tx.clone();
            let waiter = waiter.clone();
            pool.run(move || {
                waiter.wait();
                tx.send(1us).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
    }

    #[test]
    fn test_run_after() {
        let pool = ScheduledThreadPool::new(TEST_TASKS);
        let (tx, rx) = channel();

        let tx1 = tx.clone();
        pool.run_after(Duration::seconds(1), move || tx1.send(1us).unwrap());
        pool.run_after(Duration::milliseconds(500), move || tx.send(2us).unwrap());

        assert_eq!(2, rx.recv().unwrap());
        assert_eq!(1, rx.recv().unwrap());
    }

    #[test]
    fn test_jobs_complete_after_drop() {
        let pool = ScheduledThreadPool::new(TEST_TASKS);
        let (tx, rx) = channel();

        let tx1 = tx.clone();
        pool.run_after(Duration::seconds(1), move || tx1.send(1us).unwrap());
        pool.run_after(Duration::milliseconds(500), move || tx.send(2us).unwrap());

        drop(pool);

        assert_eq!(2, rx.recv().unwrap());
        assert_eq!(1, rx.recv().unwrap());
    }

    #[test]
    fn test_fixed_delay_jobs_stop_after_drop() {
        let pool = Arc::new(ScheduledThreadPool::new(TEST_TASKS));
        let (tx, rx) = channel();
        let (tx2, rx2) = channel();

        let mut pool2 = Some(pool.clone());
        let mut i = 0i32;
        pool.run_at_fixed_rate(Duration::milliseconds(500), move || {
            i += 1;
            tx.send(i).unwrap();
            rx2.recv().unwrap();
            if i == 2 {
                drop(pool2.take().unwrap());
            }
        });
        drop(pool);

        assert_eq!(Ok(1), rx.recv());
        tx2.send(()).unwrap();
        assert_eq!(Ok(2), rx.recv());
        tx2.send(()).unwrap();
        assert!(rx.recv().is_err());
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rustlex)]
#[allow(plugin_as_library)]
extern crate rustlex;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

pub mod frontend;
pub mod backend;
pub use backend::zcode::zfile;
pub mod utils;

use frontend::codegen;

use std::io::{Read,Write};

pub fn compile<R: Read, W: Write>(input: &mut R, output: &mut W) {
    // compile

    //screen
    let mut clean_input = frontend::screener::screen(input);

    // tokenize
    let tokens = frontend::lexer::lex(&mut clean_input);

    // parse tokens and create ast
    let ast = frontend::parser::parse_tokens(tokens.inspect(|ref token| {
        debug!("{:?}", token);
    }).collect()); //use collect until we work on iterators directly
    ast.print();

    // create code
    codegen::generate_zcode(ast, output);

    // for testing zcode
    backend::zcode::temp_create_zcode_example();
}
<commit_msg>-delete "temp_create_zcode_example()" call.<commit_after>#![feature(plugin)]
#![plugin(rustlex)]
#[allow(plugin_as_library)]
extern crate rustlex;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

pub mod frontend;
pub mod backend;
pub use backend::zcode::zfile;
pub mod utils;

use frontend::codegen;

use std::io::{Read,Write};

pub fn compile<R: Read, W: Write>(input: &mut R, output: &mut W) {
    // compile

    //screen
    let mut clean_input = frontend::screener::screen(input);

    // tokenize
    let tokens = frontend::lexer::lex(&mut clean_input);

    // parse tokens and create ast
    let ast = frontend::parser::parse_tokens(tokens.inspect(|ref token| {
        debug!("{:?}", token);
    }).collect()); //use collect until we work on iterators directly
    ast.print();

    // create code
    codegen::generate_zcode(ast, output);
}
<|endoftext|>


<commit_before>mod skills {
    use skills;
    use path;

    #[test]
    fn test_skills() {
        match ::skills::SkillReader(&path::Path(~"files/skills.idx"), &path::Path(~"files/skills.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(skill_reader) => {
                match skill_reader.read_skill(0) {
                    option::Some(skill) => {
                        assert skill.name == ~"Alchemy";
                        assert skill.clickable == false;
                    },
                    option::None => {
                        fail!(~"No skill at 0");
                    }
                };
                //There should be a skill at #10
                match skill_reader.read_skill(10) {
                    option::Some(_skill) => {
                        ()
                    },
                    option::None => {
                        fail!(~"No skill at 10");
                    }
                };
                //There shouldn't be 100 skills
                match skill_reader.read_skill(100) {
                    option::Some(_skill) => {
                        fail!(~"Skill at 100");
                    },
                    option::None => ()
                };
            }
        }
    }

    #[test]
    fn test_read_all() {
        match ::skills::load_skills(&path::Path(~"files/skills.idx"), &path::Path(~"files/skills.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(skill_list) => {
                assert skill_list.len() >= 49 //49 skills in the original UO
            }
        }
    }
}

mod art {
    use art;
    use path;

    #[test]
    fn test_read_tile() {
        match ::art::TileReader(&path::Path(~"files/artidx.mul"), &path::Path(~"files/art.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(tileReader) => {
                /*match tileReader.read_tile(400) {
                    option::Some(tile) => {
                        assert tile.raw_image.len() == 1012;
                        let bitmap = tile.with_transparency(0xF000);
                        assert bitmap.len() == (44*44);
                        assert bitmap[0] == 0xF000;
                        assert bitmap[21] != 0xF000;
                    },
                    option::None => {
                        error!("Couldn't read tile 400")
                        fail;
                    }
                };*/
                match tileReader.read_tile(100) {
                    option::Some(tile) => {
                        assert tile.raw_image.len() == 1012;
                        let bitmap = tile.with_transparency(0xF000);
                        assert bitmap.len() == (44*44);
                        assert bitmap[0] == 0xF000;
                        assert bitmap[21] != 0xF000;
                    },
                    option::None => {
                        fail!(~"Couldn't read tile 100")
                    }
                };
                match tileReader.read_tile(0x4000) {
                    option::Some(_tile) => {
                        fail!(~"Read static 0x4000 as tile")
                    },
                    option::None => ()
                };
            }
        }
    }

    #[test]
    fn test_read_static() {
        match ::art::TileReader(&path::Path(~"files/artidx.mul"), &path::Path(~"files/art.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(tile_reader) => {
                match tile_reader.read_static(0x4000) {
                    option::Some(static_tile) => {
                        let bitmap = static_tile.with_transparency(0xF000);
                        warn!("%u, %u, %u", bitmap.len(), static_tile.width as uint, static_tile.height as uint);
                        assert bitmap.len() == (static_tile.width + static_tile.height) as uint;
                    },
                    option::None => {
                        fail!(~"Couldn't read tile 0x4000");
                    }
                };
            }
        }
    }
}
<commit_msg>Corrected lack of importing traits in tests<commit_after>mod skills {
    use skills;
    use path;

    #[test]
    fn test_skills() {
        match ::skills::SkillReader(&path::Path(~"files/skills.idx"), &path::Path(~"files/skills.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(skill_reader) => {
                match skill_reader.read_skill(0) {
                    option::Some(skill) => {
                        assert skill.name == ~"Alchemy";
                        assert skill.clickable == false;
                    },
                    option::None => {
                        fail!(~"No skill at 0");
                    }
                };
                //There should be a skill at #10
                match skill_reader.read_skill(10) {
                    option::Some(_skill) => {
                        ()
                    },
                    option::None => {
                        fail!(~"No skill at 10");
                    }
                };
                //There shouldn't be 100 skills
                match skill_reader.read_skill(100) {
                    option::Some(_skill) => {
                        fail!(~"Skill at 100");
                    },
                    option::None => ()
                };
            }
        }
    }

    #[test]
    fn test_read_all() {
        match ::skills::load_skills(&path::Path(~"files/skills.idx"), &path::Path(~"files/skills.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(skill_list) => {
                assert skill_list.len() >= 49 //49 skills in the original UO
            }
        }
    }
}

mod art {
    use art;
    use art::Tile;
    use path;

    #[test]
    fn test_read_tile() {
        match ::art::TileReader(&path::Path(~"files/artidx.mul"), &path::Path(~"files/art.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(tileReader) => {
                /*match tileReader.read_tile(400) {
                    option::Some(tile) => {
                        assert tile.raw_image.len() == 1012;
                        let bitmap = tile.with_transparency(0xF000);
                        assert bitmap.len() == (44*44);
                        assert bitmap[0] == 0xF000;
                        assert bitmap[21] != 0xF000;
                    },
                    option::None => {
                        error!("Couldn't read tile 400")
                        fail;
                    }
                };*/
                match tileReader.read_tile(100) {
                    option::Some(tile) => {
                        assert tile.raw_image.len() == 1012;
                        let bitmap = tile.with_transparency(0xF000);
                        assert bitmap.len() == (44*44);
                        assert bitmap[0] == 0xF000;
                        assert bitmap[21] != 0xF000;
                    },
                    option::None => {
                        fail!(~"Couldn't read tile 100")
                    }
                };
                match tileReader.read_tile(0x4000) {
                    option::Some(_tile) => {
                        fail!(~"Read static 0x4000 as tile")
                    },
                    option::None => ()
                };
            }
        }
    }

    #[test]
    fn test_read_static() {
        match ::art::TileReader(&path::Path(~"files/artidx.mul"), &path::Path(~"files/art.mul")) {
            result::Err(msg) => {
                fail!(msg);
            },
            result::Ok(tile_reader) => {
                match tile_reader.read_static(0x4000) {
                    option::Some(static_tile) => {
                        let bitmap = static_tile.with_transparency(0xF000);
                        warn!("%u, %u, %u", bitmap.len(), static_tile.width as uint, static_tile.height as uint);
                        assert bitmap.len() == (static_tile.width + static_tile.height) as uint;
                    },
                    option::None => {
                        fail!(~"Couldn't read tile 0x4000");
                    }
                };
            }
        }
    }
}
<|endoftext|>


<commit_before>pub trait ASTNode {

}

pub enum Expression {

}
<commit_msg>Start on AST<commit_after>use std::fmt;

pub trait ASTNode {
    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize) -> String;
}

impl fmt::Debug for ASTNode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.print_level(0))
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum Expression {
    // Def(DefNode),
    // If(IfNode),
    // Let(LetNode),
    // Call(CallNode)
}

impl ASTNode for Expression {
    fn print_level(&self, level: usize) -> String {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::fmt;
use std::ops::{Add, AddAssign, Deref};
use std::ffi::{CString, OsString};
use std::path::{Path, PathBuf};

use super::content::{Content, ToContent};

#[derive(Debug, Default)]
pub struct Text {
    text: Vec<Content>,
}

// impl From<String> for Text {
//     fn from(s: String) -> Self {
//         Text { text: vec![Content::String(s)] }
//     }
// }

impl<T> From<T> for Text
    where T: ToContent<T>
{
    fn from(s: T) -> Self {
        Text { text: vec![Content::from(s)] }
    }
}

// impl From<OsString> for Text {
//     fn from(s: OsString) -> Self {
//         Text { text: vec![Content::OsString(s)] }
//     }
// }
//
// impl From<CString> for Text {
//     fn from(s: CString) -> Self {
//         Text { text: vec![Content::CString(s)] }
//     }
// }
//
// impl<T: Into<PathBuf>> From<T> for Text {
//     fn from(s: PathBuf) -> Self {
//         Text { text: vec![Content::PathBuf(s)] }
//     }
// }

// pub trait Textable<T> {
//     fn to_text(&self) -> Text;
// }
//
// impl<T> Textable<T> for T
//     where T: ToContent<T>
// {
//     fn to_text(&self) -> Text {
//         Text::from(self)
//     }
// }

// impl<'a> Textable for &'a str {
//     fn to_text(self) -> Text {
//         Text { text: self.to_owned() }
//     }
// }
//
// impl Textable for String {
//     fn to_text(self) -> Text {
//         Text { text: self }
//     }
// }
//
// impl<'a> Textable for &'a Path {
//     fn to_text(self) -> Text {
//         Text { text: self.to_string_lossy().into_owned() }
//     }
// }
//
// impl Textable for PathBuf {
//     fn to_text(self) -> Text {
//         Text { text: self.to_string_lossy().into_owned() }
//     }
// }

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

    pub fn len(&self) -> usize {
        let mut len: usize = 0;
        for elt in &self.text {
            len += elt.len();
        }
        len
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl fmt::Display for Text {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad(&format!("{:?}", &self.text))
    }
}

impl Deref for Text {
    type Target = str;
    fn deref(&self) -> &str {
        if self.is_empty() {
            ""
        } else {
            match self.text[0] {
                Content::String(ref s) => s,
                Content::OsString(ref s) => s.to_str().unwrap_or(""),
                Content::CString(ref s) => s.to_str().unwrap_or(""),
                Content::PathBuf(ref p) => p.to_str().unwrap_or(""),
            }
        }
    }
}

// Doesn't work - conflicting Deref implementation

// impl Deref for Text {
//     type Target = Path;
//     fn deref(&self) -> &Path {
//         Path::new(&self.text)
//     }
// }

// Add

impl Add for Text {
    type Output = Text;
    fn add(self, rhs: Text) -> Self::Output {
        let mut text = self.text.clone();
        text.extend_from_slice(&rhs.text);
        Text { text: text }
    }
}

// impl<T> Add<T> for Text
//     where T: Textable
// {
//     type Output = Text;
//     fn add(self, rhs: T) -> Self::Output {
//         Text { text: self.text + &rhs.to_text() }
//     }
// }

// AddAssign implementation

impl AddAssign for Text {
    fn add_assign(&mut self, other: Self) {
        self.text.extend_from_slice(&other.text)
    }
}

// PartialEq implementation

impl<T: ?Sized + AsRef<str>> PartialEq<T> for Text {
    default fn eq(&self, other: &T) -> bool {
        unimplemented!()
    }
}

// impl PartialEq<str> for Text {
//     fn eq(&self, other: &str) -> bool {
//         *self == Text::from(other)
//     }
// }
//
// impl<'a> PartialEq<&'a str> for Text {
//     fn eq(&self, other: &&'a str) -> bool {
//         self.text == *other
//     }
// }
//
// impl PartialEq<String> for Text {
//     fn eq(&self, other: &String) -> bool {
//         &self.text == other
//     }
// }
//
// impl<'a> PartialEq<String> for &'a Text {
//     fn eq(&self, other: &String) -> bool {
//         self.text == *other
//     }
// }
//
// impl PartialEq<Path> for Text {
//     fn eq(&self, other: &Path) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }
//
// impl<'a> PartialEq<&'a Path> for Text {
//     fn eq(&self, other: &&'a Path) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }
//
// impl PartialEq<PathBuf> for Text {
//     fn eq(&self, other: &PathBuf) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }
//
// impl<'a> PartialEq<PathBuf> for &'a Text {
//     fn eq(&self, other: &PathBuf) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }

// impl<T> From<T> for Text
//     where T: Textable
// {
//     fn from(s: T) -> Self {
//         s.to_text()
//     }
// }

// impl From<Text> for String {
//     fn from(t: Text) -> Self {
//         t.text
//     }
// }
//
// impl<'a> From<&'a Text> for &'a Path {
//     fn from(t: &'a Text) -> Self {
//         Path::new(&t.text)
//     }
// }
<commit_msg>formatting<commit_after>use std::convert::From;
use std::fmt;
use std::ops::{Add, AddAssign, Deref};
use std::ffi::{CString, OsString};
use std::path::{Path, PathBuf};

use super::content::{Content, ToContent};

#[derive(Debug, Default)]
pub struct Text {
    text: Vec<Content>,
}

// impl From<String> for Text {
//     fn from(s: String) -> Self {
//         Text { text: vec![Content::String(s)] }
//     }
// }

impl<T> From<T> for Text
    where T: ToContent<T>
{
    fn from(s: T) -> Self {
        Text { text: vec![Content::from(s)] }
    }
}

// impl From<OsString> for Text {
//     fn from(s: OsString) -> Self {
//         Text { text: vec![Content::OsString(s)] }
//     }
// }
//
// impl From<CString> for Text {
//     fn from(s: CString) -> Self {
//         Text { text: vec![Content::CString(s)] }
//     }
// }
//
// impl<T: Into<PathBuf>> From<T> for Text {
//     fn from(s: PathBuf) -> Self {
//         Text { text: vec![Content::PathBuf(s)] }
//     }
// }

// pub trait Textable<T> {
//     fn to_text(&self) -> Text;
// }
//
// impl<T> Textable<T> for T
//     where T: ToContent<T>
// {
//     fn to_text(&self) -> Text {
//         Text::from(self)
//     }
// }

// impl<'a> Textable for &'a str {
//     fn to_text(self) -> Text {
//         Text { text: self.to_owned() }
//     }
// }
//
// impl Textable for String {
//     fn to_text(self) -> Text {
//         Text { text: self }
//     }
// }
//
// impl<'a> Textable for &'a Path {
//     fn to_text(self) -> Text {
//         Text { text: self.to_string_lossy().into_owned() }
//     }
// }
//
// impl Textable for PathBuf {
//     fn to_text(self) -> Text {
//         Text { text: self.to_string_lossy().into_owned() }
//     }
// }

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

    pub fn len(&self) -> usize {
        let mut len: usize = 0;
        for elt in &self.text {
            len += elt.len();
        }
        len
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl fmt::Display for Text {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad(&format!("{:?}", &self.text))
    }
}

impl Deref for Text {
    type Target = str;
    fn deref(&self) -> &str {
        if self.is_empty() {
            ""
        } else {
            match self.text[0] {
                Content::String(ref s) => s,
                Content::OsString(ref s) => s.to_str().unwrap_or(""),
                Content::CString(ref s) => s.to_str().unwrap_or(""),
                Content::PathBuf(ref p) => p.to_str().unwrap_or(""),
            }
        }
    }
}

// Doesn't work - conflicting Deref implementation

// impl Deref for Text {
//     type Target = Path;
//     fn deref(&self) -> &Path {
//         Path::new(&self.text)
//     }
// }

// Add

impl Add for Text {
    type Output = Text;
    fn add(self, rhs: Text) -> Self::Output {
        let mut text = self.text.clone();
        text.extend_from_slice(&rhs.text);
        Text { text: text }
    }
}

// impl<T> Add<T> for Text
//     where T: Textable
// {
//     type Output = Text;
//     fn add(self, rhs: T) -> Self::Output {
//         Text { text: self.text + &rhs.to_text() }
//     }
// }

// AddAssign implementation

impl AddAssign for Text {
    fn add_assign(&mut self, other: Self) {
        self.text.extend_from_slice(&other.text)
    }
}

// PartialEq implementation

impl<T: ?Sized + AsRef<str>> PartialEq<T> for Text {
    default fn eq(&self, other: &T) -> bool {
        unimplemented!()
    }
}

// impl PartialEq<str> for Text {
//     fn eq(&self, other: &str) -> bool {
//         *self == Text::from(other)
//     }
// }

// impl<'a> PartialEq<&'a str> for Text {
//     fn eq(&self, other: &&'a str) -> bool {
//         self.text == *other
//     }
// }
//
// impl PartialEq<String> for Text {
//     fn eq(&self, other: &String) -> bool {
//         &self.text == other
//     }
// }
//
// impl<'a> PartialEq<String> for &'a Text {
//     fn eq(&self, other: &String) -> bool {
//         self.text == *other
//     }
// }
//
// impl PartialEq<Path> for Text {
//     fn eq(&self, other: &Path) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }

// impl<'a> PartialEq<&'a Path> for Text {
//     fn eq(&self, other: &&'a Path) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }

// impl PartialEq<PathBuf> for Text {
//     fn eq(&self, other: &PathBuf) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }

// impl<'a> PartialEq<PathBuf> for &'a Text {
//     fn eq(&self, other: &PathBuf) -> bool {
//         match other.to_str() {
//             Some(s) => self.text == s,
//             None => false,
//         }
//     }
// }

// impl<T> From<T> for Text
//     where T: Textable
// {
//     fn from(s: T) -> Self {
//         s.to_text()
//     }
// }

// impl From<Text> for String {
//     fn from(t: Text) -> Self {
//         t.text
//     }
// }
//
// impl<'a> From<&'a Text> for &'a Path {
//     fn from(t: &'a Text) -> Self {
//         Path::new(&t.text)
//     }
// }
<|endoftext|>