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

use std::thread;
use std::net::{TcpListener, ToSocketAddrs};
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver
};

use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use simple_stream::nbetstream::NbetStream;
use stats;
use types::*;
use socket::Socket;
use resources::ResourcePool;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLIN      - Available for read
// EPOLLRDHUP   - Connection has been closed
// EPOLLONESHOT - After an event has been received, and reported, do not track
//                further changes until explicitly told to do so.
const EVENTS: u32 = (
    event_type::EPOLLET | // Set fd to EdgeTrigger mode
    event_type::EPOLLIN |
    event_type::EPOLLRDHUP |
    event_type::EPOLLONESHOT);

pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // EpollEvent handler thread
    let epfd1 = epfd.clone();
    let sockets1 = sockets.clone();
    let (tx_ep_event, rx_ep_event): (Sender<EpollEvent>, Receiver<EpollEvent>) = channel();
    let safe_handler = Arc::new(Mutex::new(*handler));
    thread::Builder::new()
        .name("EpollEvent Handler".to_string())
        .spawn(move || {
            epoll_event_handler(epfd1, rx_ep_event, sockets1, safe_handler);
        }).unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            epoll_wait_loop(epfd2, tx_ep_event);
        }).unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let sockets2 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
            listen(address, epfd3, sockets2);
        }).unwrap();

    // Stay alive forever
    let _ = prox.join();
}

fn listen<T: ToSocketAddrs>(address: T, epfd: RawFd, sockets: SocketList) {
    let listener = TcpListener::bind(address).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                trace!("New connection received");
                // Create new socket
                match NbetStream::new(stream) {
                    Ok(nb_stream) => {
                        let socket = Socket::new(nb_stream);
                        let socket_ptr;
                        // Add to master list
                        { // Begin Mutex lock
                            let mut guard = match sockets.lock() {
                                Ok(guard) => guard,
                                Err(poisoned) => {
                                    warn!("SocketList Mutex failed, using anyway...");
                                    poisoned.into_inner()
                                }
                            };
                            let socket_list = guard.deref_mut();
                            socket_list.push_back(socket.clone());
                            socket_ptr = socket_list.back_mut().unwrap() as *mut Socket;
                        } // End Mutex lock

                        // Add to epoll
                        let sfd = socket.raw_fd();
                        let mut event = EpollEvent {
                            data: socket_ptr as u64,
                            events: EVENTS
                        };
                        match epoll::ctl(epfd, ctl_op::ADD, sfd, &mut event) {
                            Ok(()) => {
                                trace!("New socket added to epoll list");
                                trace!("socket.id: {}", socket.id());
                                trace!("epfd: {}", epfd);
                                trace!("fd: {}", sfd);
                            },
                            Err(e) => warn!("Epoll CtrlError during add: {}", e)
                        };
                    }
                    Err(e) => warn!("Error creating nbstream: {}", e)
                }
            }
            Err(e) => warn!("Error encountered during TCP connection: {}", e)
        }
    }
    drop(listener);
}

fn epoll_wait_loop(epfd: RawFd, tx_handler: Sender<EpollEvent>) {
    // Maximum number of events we want to be notified of at one time
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe { events.set_len(100); }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    let _ = tx_handler.send(events[x]);
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        }
    }
}

fn epoll_event_handler(epfd: RawFd,
                       rx: Receiver<EpollEvent>,
                       sockets: SocketList,
                       handler: SafeHandler) {
    // Types of events we care about
    const READ_EVENT: u32 = event_type::EPOLLIN;
    const DROP_EVENT: u32 = event_type::EPOLLRDHUP | event_type::EPOLLHUP;

    // Thread pool
    let mut pool = ResourcePool::new();

    for event in rx.iter() {
        // Get a pointer to the socket in the list
        let socket;
        { // Begin Mutex lock
            let _ = match sockets.lock() {
                Ok(guard) => guard,
                Err(poisoned) => {
                    warn!("SocketList Mutex failed, using anyway...");
                    poisoned.into_inner()
                }
            };
            socket = event.data as *mut Socket;
        } // End Mutex lock

        if (event.events & DROP_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socketfd = unsafe { (*socket).raw_fd() };
            let socketid = unsafe { (*socket).id() };

            pool.run(move || {
                epoll_remove_fd(t_epfd, socketfd);
                remove_socket_from_list(socketid, socket_list.clone());
                { // EventHandler Mutex locked
                    let mut guard = match t_handler.lock() {
                        Ok(guard) => guard,
                        Err(poisoned) => {
                            warn!("EventHandler Mutex failed, using anyway...");
                            poisoned.into_inner()
                        }
                    };
                    let e_handler = guard.deref_mut();
                    e_handler.on_socket_closed(socketid);
                } // EventHandler Mutex unlocked
            });
        } else if (event.events & READ_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let mut s_clone = unsafe { (*socket).clone() };
            let socketfd = s_clone.raw_fd();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socket_ptr = socket as u64;

            trace!("fd test...");
            trace!("c1.fd: {}", s_clone.raw_fd());

            let c2 = s_clone.clone();
            trace!("c2.fd: {}", c2.raw_fd());

            // Rust's TcpStream clone method makes use of the F_DUPFD flag for duplicating
            // file descriptors. This means the fd we currently have associated for this
            // stream is now worthless within epoll, and why we're grabbing it off of a raw
            // pointer dereference. Instead of setting it back to listening with ctl::MOD,
            // we'll remove it and add the new file descriptor given from the system.
            let orig_fd = unsafe { (*socket).raw_fd() };

            // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
            // a non-null pointer in event, even though this argument is ignored.
            // Since Linux 2.6.9, event can be specified as NULL when using
            // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
            // before 2.6.9 should specify a non-null pointer in event.
            let mut event = EpollEvent {
                data: 0u64,
                events: 0u32
            };
            match epoll::ctl(t_epfd.clone(), ctl_op::DEL, orig_fd, &mut event) {
                Ok(_) => trace!("Socket removed from epoll list"),
                Err(e) => {
                    warn!("Epoll CtrlError during mod: {}", e);
                    warn!("s.id: {}", unsafe { (*socket).id() });
                    warn!("epfd: {}", t_epfd.clone());
                    warn!("fd: {}", socketfd);
                }
            };

            pool.run(move || {
                match s_clone.read() {
                    Ok(_) => {
                        for msg in s_clone.buffer().iter() {
                            let debug_msg = msg.clone();
                            match String::from_utf8(debug_msg) {
                                Ok(msg_str) => trace!("msg: {}", msg_str),
                                Err(_) => trace!("msg not UTF-8")
                            };

                            { // EventHandler Mutex locked
                                let mut guard = match t_handler.lock() {
                                    Ok(guard) => guard,
                                    Err(poisoned) => {
                                        warn!("EventHandler Mutex failed, using anyway...");
                                        poisoned.into_inner()
                                    }
                                };
                                let e_handler = guard.deref_mut();
                                e_handler.on_data_received(s_clone.clone(),
                                    socket_list.clone(), msg.clone());
                            } // EventHandler Mutex unlocked

                            // Track message received event and num bytes received
                            stats::msg_recv();
                            stats::bytes_recv(msg.len());

                            // Add socket's fd back to epoll watch list
                            let mut event = EpollEvent {
                                data: socket_ptr,
                                events: EVENTS
                            };
                            let s_id = s_clone.id();
                            match epoll::ctl(t_epfd.clone(), ctl_op::ADD, socketfd, &mut event) {
                                Ok(_) => trace!("Socket back in epoll list"),
                                Err(e) => {
                                    warn!("Epoll CtrlError during mod: {}", e);
                                    warn!("s.id: {}", s_id);
                                    warn!("epfd: {}", t_epfd.clone());
                                    warn!("fd: {}", socketfd);
                                }
                            };
                        }
                    }
                    Err(e) => {
                        debug!("Error reading socket: {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_id = s_clone.id();
                        epoll_remove_fd(t_epfd, socketfd);
                        remove_socket_from_list(s_id, socket_list.clone());
                        let mut guard = match t_handler.lock() {
                            Ok(guard) => guard,
                            Err(poisoned) => {
                                warn!("SocketList Mutex failed, using anyway...");
                                poisoned.into_inner()
                            }
                        };
                        let e_handler = guard.deref_mut();
                        e_handler.on_socket_closed(s_id);
                    }
                };
            });
        } else { warn!("Unknown epoll event received: {}", event.data); continue; }
    }
}

fn epoll_remove_fd(epfd: RawFd, fd: RawFd) {
    debug!("remove_socket_from_epoll");

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
    // before 2.6.9 should specify a non-null pointer in event.
    let mut rm_event = EpollEvent {
        data: 0 as u64,
        events: 0 as u32
    };

    // Depending on how fds are duplicated with .clone(), this may fail.
    //
    // If the failure case is CtlError::ENOENT, we do not care, because
    // epoll will clean the up the descriptor after they are all dropped from
    // program memory
    match epoll::ctl(epfd, ctl_op::DEL, fd, &mut rm_event) {
        Ok(()) => trace!("Socket removed from epoll watch list"),
        Err(e) => {
            match e {
                CtlError::ENOENT => {
                    trace!("Fd not found in epoll, will remove when fd is syscall closed");
                }
                _ => warn!("Epoll CtrlError during del: {}", e)
            }
        }
    };
}

/// Removes socket_ids from master list
fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
    debug!("remove_socket_from_list");

    let mut s_guard = match sockets.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("SocketList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let s_list = s_guard.deref_mut();

    let mut s_found = false;
    let mut index = 1usize;
    for s in s_list.iter() {
        if s.id() == socket_id {
            s_found = true;
            break;
        }
        index += 1;
    }

    if !s_found { return; }

    if index == 1 {
        s_list.pop_front();
    } else {
        let mut split = s_list.split_off(index - 1);
        split.pop_front();
        s_list.append(&mut split);
    }

    stats::conn_lost();

    trace!("socket removed from list");
}
<commit_msg>Stupid F_DUPFD flag<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::thread;
use std::net::{TcpListener, ToSocketAddrs};
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver
};

use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use simple_stream::nbetstream::NbetStream;
use stats;
use types::*;
use socket::Socket;
use resources::ResourcePool;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLIN      - Available for read
// EPOLLRDHUP   - Connection has been closed
// EPOLLONESHOT - After an event has been received, and reported, do not track
//                further changes until explicitly told to do so.
const EVENTS: u32 = (
    event_type::EPOLLET | // Set fd to EdgeTrigger mode
    event_type::EPOLLIN |
    event_type::EPOLLRDHUP |
    event_type::EPOLLONESHOT);

pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // EpollEvent handler thread
    let epfd1 = epfd.clone();
    let sockets1 = sockets.clone();
    let (tx_ep_event, rx_ep_event): (Sender<EpollEvent>, Receiver<EpollEvent>) = channel();
    let safe_handler = Arc::new(Mutex::new(*handler));
    thread::Builder::new()
        .name("EpollEvent Handler".to_string())
        .spawn(move || {
            epoll_event_handler(epfd1, rx_ep_event, sockets1, safe_handler);
        }).unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            epoll_wait_loop(epfd2, tx_ep_event);
        }).unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let sockets2 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
            listen(address, epfd3, sockets2);
        }).unwrap();

    // Stay alive forever
    let _ = prox.join();
}

fn listen<T: ToSocketAddrs>(address: T, epfd: RawFd, sockets: SocketList) {
    let listener = TcpListener::bind(address).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                trace!("New connection received");
                // Create new socket
                match NbetStream::new(stream) {
                    Ok(nb_stream) => {
                        let socket = Socket::new(nb_stream);
                        let socket_ptr;
                        // Add to master list
                        { // Begin Mutex lock
                            let mut guard = match sockets.lock() {
                                Ok(guard) => guard,
                                Err(poisoned) => {
                                    warn!("SocketList Mutex failed, using anyway...");
                                    poisoned.into_inner()
                                }
                            };
                            let socket_list = guard.deref_mut();
                            socket_list.push_back(socket.clone());
                            socket_ptr = socket_list.back_mut().unwrap() as *mut Socket;
                        } // End Mutex lock

                        // Add to epoll
                        let sfd = socket.raw_fd();
                        let mut event = EpollEvent {
                            data: socket_ptr as u64,
                            events: EVENTS
                        };
                        match epoll::ctl(epfd, ctl_op::ADD, sfd, &mut event) {
                            Ok(()) => {
                                trace!("New socket added to epoll list");
                                trace!("socket.id: {}", socket.id());
                                trace!("epfd: {}", epfd);
                                trace!("fd: {}", sfd);
                            },
                            Err(e) => warn!("Epoll CtrlError during add: {}", e)
                        };
                    }
                    Err(e) => warn!("Error creating nbstream: {}", e)
                }
            }
            Err(e) => warn!("Error encountered during TCP connection: {}", e)
        }
    }
    drop(listener);
}

fn epoll_wait_loop(epfd: RawFd, tx_handler: Sender<EpollEvent>) {
    // Maximum number of events we want to be notified of at one time
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe { events.set_len(100); }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    let _ = tx_handler.send(events[x]);
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        }
    }
}

fn epoll_event_handler(epfd: RawFd,
                       rx: Receiver<EpollEvent>,
                       sockets: SocketList,
                       handler: SafeHandler) {
    // Types of events we care about
    const READ_EVENT: u32 = event_type::EPOLLIN;
    const DROP_EVENT: u32 = event_type::EPOLLRDHUP | event_type::EPOLLHUP;

    // Thread pool
    let mut pool = ResourcePool::new();

    for event in rx.iter() {
        // Get a pointer to the socket in the list
        let socket;
        { // Begin Mutex lock
            let _ = match sockets.lock() {
                Ok(guard) => guard,
                Err(poisoned) => {
                    warn!("SocketList Mutex failed, using anyway...");
                    poisoned.into_inner()
                }
            };
            socket = event.data as *mut Socket;
        } // End Mutex lock

        if (event.events & DROP_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socketfd = unsafe { (*socket).raw_fd() };
            let socketid = unsafe { (*socket).id() };

            pool.run(move || {
                epoll_remove_fd(t_epfd, socketfd);
                remove_socket_from_list(socketid, socket_list.clone());
                { // EventHandler Mutex locked
                    let mut guard = match t_handler.lock() {
                        Ok(guard) => guard,
                        Err(poisoned) => {
                            warn!("EventHandler Mutex failed, using anyway...");
                            poisoned.into_inner()
                        }
                    };
                    let e_handler = guard.deref_mut();
                    e_handler.on_socket_closed(socketid);
                } // EventHandler Mutex unlocked
            });
        } else if (event.events & READ_EVENT) > 0 {
            let t_epfd = epfd.clone();
            let mut s_clone = unsafe { (*socket).clone() };
            let socketfd = s_clone.raw_fd();
            let socket_list = sockets.clone();
            let t_handler = handler.clone();
            let socket_ptr = socket as u64;

            pool.run(move || {
                match s_clone.read() {
                    Ok(_) => {
                        for msg in s_clone.buffer().iter() {
                            let debug_msg = msg.clone();
                            match String::from_utf8(debug_msg) {
                                Ok(msg_str) => trace!("msg: {}", msg_str),
                                Err(_) => trace!("msg not UTF-8")
                            };

                            { // EventHandler Mutex locked
                                let mut guard = match t_handler.lock() {
                                    Ok(guard) => guard,
                                    Err(poisoned) => {
                                        warn!("EventHandler Mutex failed, using anyway...");
                                        poisoned.into_inner()
                                    }
                                };
                                let e_handler = guard.deref_mut();
                                e_handler.on_data_received(s_clone.clone(),
                                    socket_list.clone(), msg.clone());
                            } // EventHandler Mutex unlocked

                            // Track message received event and num bytes received
                            stats::msg_recv();
                            stats::bytes_recv(msg.len());

                            // Add socket's fd to epoll watch list
                            //
                            // Rust's TcpStream clone method makes use of the F_DUPFD flag
                            // for duplicating file descriptors. This means the fd we just read
                            // from and/or the original fd added to epoll for this stream cannot
                            // be used to MOD, or DEL and ADD again, in order to re-register for
                            // the same events, with the same fd.
                            // The originally added fd is essentially invalid at this point, but
                            // lucky for us, Rust sets the CLOEXEC flag for fds, which means that
                            // the system will clean them up when they go out of scope. Also,
                            // epoll removes fds when the system clears them, so we should be OK
                            // from any internal fd leaks here.
                            let mut event = EpollEvent {
                                data: socket_ptr,
                                events: EVENTS
                            };
                            let s_id = s_clone.id();
                            match epoll::ctl(t_epfd.clone(), ctl_op::ADD, socketfd, &mut event) {
                                Ok(_) => trace!("Socket back in epoll list"),
                                Err(e) => {
                                    warn!("Epoll CtrlError during mod: {}", e);
                                    warn!("s.id: {}", s_id);
                                    warn!("epfd: {}", t_epfd.clone());
                                    warn!("fd: {}", socketfd);
                                }
                            };
                        }
                    }
                    Err(e) => {
                        debug!("Error reading socket: {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_id = s_clone.id();
                        epoll_remove_fd(t_epfd, socketfd);
                        remove_socket_from_list(s_id, socket_list.clone());
                        let mut guard = match t_handler.lock() {
                            Ok(guard) => guard,
                            Err(poisoned) => {
                                warn!("SocketList Mutex failed, using anyway...");
                                poisoned.into_inner()
                            }
                        };
                        let e_handler = guard.deref_mut();
                        e_handler.on_socket_closed(s_id);
                    }
                };
            });
        } else { warn!("Unknown epoll event received: {}", event.data); continue; }
    }
}

fn epoll_remove_fd(epfd: RawFd, fd: RawFd) {
    debug!("remove_socket_from_epoll");

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
    // before 2.6.9 should specify a non-null pointer in event.
    let mut rm_event = EpollEvent {
        data: 0 as u64,
        events: 0 as u32
    };

    // Depending on how fds are duplicated with .clone(), this may fail.
    //
    // If the failure case is CtlError::ENOENT, we do not care, because
    // epoll will clean the up the descriptor after they are all dropped from
    // program memory
    match epoll::ctl(epfd, ctl_op::DEL, fd, &mut rm_event) {
        Ok(()) => trace!("Socket removed from epoll watch list"),
        Err(e) => {
            match e {
                CtlError::ENOENT => {
                    trace!("Fd not found in epoll, will remove when fd is syscall closed");
                }
                _ => warn!("Epoll CtrlError during del: {}", e)
            }
        }
    };
}

/// Removes socket_ids from master list
fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
    debug!("remove_socket_from_list");

    let mut s_guard = match sockets.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("SocketList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let s_list = s_guard.deref_mut();

    let mut s_found = false;
    let mut index = 1usize;
    for s in s_list.iter() {
        if s.id() == socket_id {
            s_found = true;
            break;
        }
        index += 1;
    }

    if !s_found { return; }

    if index == 1 {
        s_list.pop_front();
    } else {
        let mut split = s_list.split_off(index - 1);
        split.pop_front();
        s_list.append(&mut split);
    }

    stats::conn_lost();

    trace!("socket removed from list");
}
<|endoftext|>


<commit_before>use lexer::{Symbol, Token, Tokens};
use function::{Function, Functions, functions};
use error::EvaluatorError;
use constants::{VERSION, KEYWORDS, HELP, LICENSE};

pub struct Evaluator {
    functions: Functions,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator { functions: Functions::new() }
    }

    fn is_keyword(&self, variable: &String) -> Option<&'static str> {
        for keyword in KEYWORDS {
            if keyword.to_string() == variable.to_lowercase() {
                return Some(keyword);
            }
        }

        None
    }

    pub fn evaluate(&self, tokens: Tokens) -> Result<Vec<String>, EvaluatorError> {
        let mut result: Vec<String> = Vec::with_capacity(3);
        let mut stack: Vec<i32> = Vec::with_capacity(3);
        let num_tokens = tokens.len();

        if tokens.is_empty() {
            return Ok(result);
        }

        for (position, ref token) in tokens {
            match *token {
                Token::Decimal(ref dec) => {
                    stack.push(dec.parse().unwrap());
                }
                Token::Variable(ref var) => {
                    if let Some(kw) = self.is_keyword(var) {
                        if num_tokens == 1 {
                            match kw {
                                "version" => result.push(VERSION.to_string()),
                                "help" => {
                                    let mut h = HELP.lines()
                                        .map(|line| line.to_string())
                                        .collect();
                                    result.append(&mut h);
                                }
                                "license" => {
                                    let mut l = LICENSE.lines()
                                        .map(|line| line.to_string())
                                        .collect();
                                    result.append(&mut l);
                                }
                                "exit" => return Err(EvaluatorError::Exit),
                                _ => unreachable!(),
                            }
                            return Ok(result);
                        } else {
                            return Err(EvaluatorError::KeywordError(position));
                        }
                    } else {
                        return Err(EvaluatorError::UnknownKeyword(position));
                    }
                }
                Token::Operator(ref op) => {
                    let function = self.functions.get(&op).unwrap();
                    if stack.len() >= function.arity {
                        let stack_len = stack.len();
                        let args: Vec<i32> = stack.split_off(stack_len - function.arity);
                        let interm_result = try!((function.handle)(args, position));
                        stack.push(interm_result.0);
                        result.push(interm_result.1);
                        result.push(interm_result.0.to_string());
                    } else {
                        return Err(EvaluatorError::MissingArgument(position));
                    }
                }
                _ => continue,

            }
        }

        // The last element on the stack should be the final result
        if stack.len() != 1 {
            return Err(EvaluatorError::TooManyArguments);
        }

        Ok(result)
    }
}

impl Default for Evaluator {
    fn default() -> Evaluator {
        let mut evaluator = Evaluator::new();

        evaluator.functions.insert(Symbol::NOT, Function::new(1, Box::new(functions::not)));
        evaluator.functions.insert(Symbol::XOR, Function::new(2, Box::new(functions::xor)));
        evaluator.functions.insert(Symbol::OR, Function::new(2, Box::new(functions::or)));
        evaluator.functions.insert(Symbol::AND, Function::new(2, Box::new(functions::and)));
        evaluator.functions.insert(Symbol::LSHIFT,
                                   Function::new(2, Box::new(functions::lshift)));
        evaluator.functions.insert(Symbol::RSHIFT,
                                   Function::new(2, Box::new(functions::rshift)));

        evaluator
    }
}
<commit_msg>Account for empty result case if stack hasn't been popped<commit_after>use lexer::{Symbol, Token, Tokens};
use function::{Function, Functions, functions};
use error::EvaluatorError;
use constants::{VERSION, KEYWORDS, HELP, LICENSE};

pub struct Evaluator {
    functions: Functions,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator { functions: Functions::new() }
    }

    fn is_keyword(&self, variable: &String) -> Option<&'static str> {
        for keyword in KEYWORDS {
            if keyword.to_string() == variable.to_lowercase() {
                return Some(keyword);
            }
        }

        None
    }

    pub fn evaluate(&self, tokens: Tokens) -> Result<Vec<String>, EvaluatorError> {
        let mut result: Vec<String> = Vec::with_capacity(3);
        let mut stack: Vec<i32> = Vec::with_capacity(3);
        let num_tokens = tokens.len();

        if tokens.is_empty() {
            return Ok(result);
        }

        for (position, ref token) in tokens {
            match *token {
                Token::Decimal(ref dec) => {
                    stack.push(dec.parse().unwrap());
                }
                Token::Variable(ref var) => {
                    if let Some(kw) = self.is_keyword(var) {
                        if num_tokens == 1 {
                            match kw {
                                "version" => result.push(VERSION.to_string()),
                                "help" => {
                                    let mut h = HELP.lines()
                                        .map(|line| line.to_string())
                                        .collect();
                                    result.append(&mut h);
                                }
                                "license" => {
                                    let mut l = LICENSE.lines()
                                        .map(|line| line.to_string())
                                        .collect();
                                    result.append(&mut l);
                                }
                                "exit" => return Err(EvaluatorError::Exit),
                                _ => unreachable!(),
                            }
                            return Ok(result);
                        } else {
                            return Err(EvaluatorError::KeywordError(position));
                        }
                    } else {
                        return Err(EvaluatorError::UnknownKeyword(position));
                    }
                }
                Token::Operator(ref op) => {
                    let function = self.functions.get(&op).unwrap();
                    if stack.len() >= function.arity {
                        let stack_len = stack.len();
                        let args: Vec<i32> = stack.split_off(stack_len - function.arity);
                        let interm_result = try!((function.handle)(args, position));
                        stack.push(interm_result.0);
                        result.push(interm_result.1);
                        result.push(interm_result.0.to_string());
                    } else {
                        return Err(EvaluatorError::MissingArgument(position));
                    }
                }
                _ => continue,

            }
        }

        // The last element on the stack should be the final result
        if stack.len() != 1 {
            return Err(EvaluatorError::TooManyArguments);
        } else if result.is_empty() {
            result.push(stack.pop().unwrap().to_string());
        }

        Ok(result)
    }
}

impl Default for Evaluator {
    fn default() -> Evaluator {
        let mut evaluator = Evaluator::new();

        evaluator.functions.insert(Symbol::NOT, Function::new(1, Box::new(functions::not)));
        evaluator.functions.insert(Symbol::XOR, Function::new(2, Box::new(functions::xor)));
        evaluator.functions.insert(Symbol::OR, Function::new(2, Box::new(functions::or)));
        evaluator.functions.insert(Symbol::AND, Function::new(2, Box::new(functions::and)));
        evaluator.functions.insert(Symbol::LSHIFT,
                                   Function::new(2, Box::new(functions::lshift)));
        evaluator.functions.insert(Symbol::RSHIFT,
                                   Function::new(2, Box::new(functions::rshift)));

        evaluator
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use comrak;
use parse::{Parser, Node, NodeValue};
use directives;

pub struct Evaluator {
    directives: HashMap<String, Box<directives::DirectiveHandler>>,
    pub parser: RefCell<Parser>,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator {
            directives: HashMap::new(),
            parser: RefCell::new(Parser::new()),
        }
    }

    pub fn register<S: Into<String>>(&mut self,
                                     name: S,
                                     handler: Box<directives::DirectiveHandler>) {
        self.directives.insert(name.into(), handler);
    }

    pub fn evaluate(&self, node: &Node) -> String {
        match node.value {
            NodeValue::Owned(ref s) => s.to_owned(),
            NodeValue::Children(ref children) => {
                if let Some(first_element) = children.get(0) {
                    let directive_name = match first_element.value {
                        NodeValue::Owned(ref dname) => Cow::Borrowed(dname),
                        NodeValue::Children(_) => Cow::Owned(self.evaluate(first_element)),
                    };

                    if let Some(handler) = self.directives.get(directive_name.as_ref()) {
                        return match handler.handle(self, &children[1..]) {
                                   Ok(s) => s,
                                   Err(_) => {
                                       println!("Error in directive {:?}", directive_name);
                                       return "".to_owned();
                                   }
                               };
                    }

                    println!("Unknown directive {:?}", directive_name);
                    "".to_owned()
                } else {
                    println!("Empty node");
                    "".to_owned()
                }
            }
        }
    }

    pub fn render_markdown(&self, markdown: &str) -> String {
        let mut options = comrak::ComrakOptions::default();
        options.github_pre_lang = true;
        options.ext_strikethrough = true;
        options.ext_table = true;

        comrak::markdown_to_html(markdown, &options)
    }
}
<commit_msg>Add simple warn/error framework<commit_after>use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::Path;
use parse::{Parser, Node, NodeValue};
use comrak;
use log;
use directives;

pub struct Evaluator {
    directives: HashMap<String, Box<directives::DirectiveHandler>>,
    pub parser: RefCell<Parser>,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator {
            directives: HashMap::new(),
            parser: RefCell::new(Parser::new()),
        }
    }

    pub fn register<S: Into<String>>(&mut self,
                                     name: S,
                                     handler: Box<directives::DirectiveHandler>) {
        self.directives.insert(name.into(), handler);
    }

    pub fn evaluate(&self, node: &Node) -> String {
        match node.value {
            NodeValue::Owned(ref s) => s.to_owned(),
            NodeValue::Children(ref children) => {
                if let Some(first_element) = children.get(0) {
                    let directive_name = match first_element.value {
                        NodeValue::Owned(ref dname) => Cow::Borrowed(dname),
                        NodeValue::Children(_) => Cow::Owned(self.evaluate(first_element)),
                    };

                    if let Some(handler) = self.directives.get(directive_name.as_ref()) {
                        return match handler.handle(self, &children[1..]) {
                                   Ok(s) => s,
                                   Err(_) => {
                                       self.error(&children[1], &format!("Error in directive {}", directive_name));
                                       return "".to_owned();
                                   }
                               };
                    }

                    println!("Unknown directive {:?}", directive_name);
                    "".to_owned()
                } else {
                    println!("Empty node");
                    "".to_owned()
                }
            }
        }
    }

    pub fn render_markdown(&self, markdown: &str) -> String {
        let mut options = comrak::ComrakOptions::default();
        options.github_pre_lang = true;
        options.ext_strikethrough = true;
        options.ext_table = true;

        comrak::markdown_to_html(markdown, &options)
    }

    pub fn log(&self, node: &Node, message: &str, level: log::LogLevel) {
        let parser = self.parser.borrow();
        let file_path = parser.get_node_source_path(node);
        log!(level, "{}\n  --> {}:?:?", message, file_path.unwrap_or_else(|| Path::new("")).to_string_lossy());
    }

    #[allow(dead_code)]
    pub fn warn(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Warn);
    }

    pub fn error(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Error);
    }
}
<|endoftext|>


<commit_before>//! Methods for reading hue data out of hues.rs
//!
//! Hues are represented in a continuous, unindexed file as groups -
//! `|header: u32|hues: [HueEntry..8]`
//!
//! Individual HueEntries are defined as
//! `|color_table:[u16..32]|table_start:u16|table_end:u16|name:[u8..20]|`
//!
use std::io::{File, Open, Read, IoResult, SeekSet, MemWriter};
use utils::MEMWRITER_ERROR;

/**
 * An individual Hue
 */
pub struct Hue {
    ///32 color values
    pub color_table: [u16, ..32],
    ///Unknown usage
    pub table_start: u16,
    ///Unknown usage
    pub table_end: u16,
    ///A label for the hue
    pub name: String
}

impl Clone for Hue {

    fn clone(&self) -> Hue {
        Hue {
            color_table: self.color_table,
            table_start: self.table_start,
            table_end: self.table_end,
            name: self.name.clone()
        }
    }
}

impl Hue {
    pub fn new(color_table: [u16, ..32], table_start: u16, table_end: u16, name: String) -> Hue {
        Hue {
            color_table: color_table,
            table_start: table_start,
            table_end: table_end,
            name: name
        }
    }

    /**
     * Convert a hue back into its canonical mul representation
     */
    pub fn serialize(&self) -> Vec<u8> {
        let mut writer = MemWriter::new();
        for color in self.color_table.iter() {
            writer.write_le_u16(*color).ok().expect(MEMWRITER_ERROR);
        }
        writer.write_le_u16(self.table_start).ok().expect(MEMWRITER_ERROR);
        writer.write_le_u16(self.table_end).ok().expect(MEMWRITER_ERROR);

        let raw_string = self.name.clone().to_c_str();

        writer.write(raw_string.as_bytes()).ok().expect(MEMWRITER_ERROR);
        writer.write(Vec::from_elem(20 - raw_string.len() - 1, 0).as_slice()).ok().expect(MEMWRITER_ERROR);

        let output = writer.unwrap();
        assert_eq!(output.len(), ENTRY_SIZE);

        output
    }
}

/**
 * A collection of 8 hues
 */
pub struct HueGroup {
    ///Unknown usage
    pub header: u32,
    pub entries: [Hue, ..8]
}

impl HueGroup {

    pub fn new(header: u32, entries: [Hue, ..8]) -> HueGroup {
        HueGroup {
            header: header,
            entries: entries
        }
    }

    pub fn serialize(&self) -> Vec<u8> {
        let mut writer = MemWriter::new();
        writer.write_le_u32(self.header).ok().expect(MEMWRITER_ERROR);
        for hue in self.entries.iter() {
            writer.write(hue.serialize().as_slice()).ok().expect(MEMWRITER_ERROR);
        }
        writer.unwrap()
    }
}

//A hue_entry is (32 * 2) + 2 + 2 + 20 bytes = 88 bytes
const ENTRY_SIZE: uint = 88;
//8 entries to a group, plus a 4 byte header. 708 bytes.
const GROUP_SIZE: uint = (ENTRY_SIZE * 8) + 4;

pub struct HueReader {
    data_reader: File
}

impl HueReader {
    pub fn new(hues_path: &Path) -> IoResult<HueReader> {
        let data_reader = try!(File::open_mode(hues_path, Open, Read));

        Ok(HueReader {
            data_reader: data_reader
        })
    }

    /**
     * Read the given indexed group
     */
    pub fn read_hue_group(&mut self, id: u32) -> IoResult<HueGroup> {
        try!(self.data_reader.seek((id as uint * GROUP_SIZE) as i64, SeekSet));

        let header = try!(self.data_reader.read_le_u32());

        let entries: [Hue, ..8] = [
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue())
        ];

        Ok(HueGroup {
            header: header,
            entries: entries
        })
    }

    fn read_hue(&mut self) -> IoResult<Hue> {
        let mut color_table = [0u16, ..32];
        for idx in range(0u, 32) {
            color_table[idx] = try!(self.data_reader.read_le_u16());
        }
        Ok(Hue::new(
            color_table,
            try!(self.data_reader.read_le_u16()),
            try!(self.data_reader.read_le_u16()),
            try!(self.data_reader.read_exact(20)).into_ascii().into_string()
        ))

    }
}

<commit_msg>Corrected hue name loading<commit_after>//! Methods for reading hue data out of hues.rs
//!
//! Hues are represented in a continuous, unindexed file as groups -
//! `|header: u32|hues: [HueEntry..8]`
//!
//! Individual HueEntries are defined as
//! `|color_table:[u16..32]|table_start:u16|table_end:u16|name:[u8..20]|`
//!
use std::io::{File, Open, Read, IoResult, SeekSet, MemWriter};
use utils::MEMWRITER_ERROR;

/**
 * An individual Hue
 */
pub struct Hue {
    ///32 color values
    pub color_table: [u16, ..32],
    ///Unknown usage
    pub table_start: u16,
    ///Unknown usage
    pub table_end: u16,
    ///A label for the hue
    pub name: String
}

impl Clone for Hue {

    fn clone(&self) -> Hue {
        Hue {
            color_table: self.color_table,
            table_start: self.table_start,
            table_end: self.table_end,
            name: self.name.clone()
        }
    }
}

impl Hue {
    pub fn new(color_table: [u16, ..32], table_start: u16, table_end: u16, name: String) -> Hue {
        Hue {
            color_table: color_table,
            table_start: table_start,
            table_end: table_end,
            name: name
        }
    }

    /**
     * Convert a hue back into its canonical mul representation
     */
    pub fn serialize(&self) -> Vec<u8> {
        let mut writer = MemWriter::new();
        for color in self.color_table.iter() {
            writer.write_le_u16(*color).ok().expect(MEMWRITER_ERROR);
        }
        writer.write_le_u16(self.table_start).ok().expect(MEMWRITER_ERROR);
        writer.write_le_u16(self.table_end).ok().expect(MEMWRITER_ERROR);

        let raw_string = self.name.clone().to_c_str();

        writer.write(raw_string.as_bytes()).ok().expect(MEMWRITER_ERROR);
        writer.write(Vec::from_elem(20 - raw_string.len() - 1, 0).as_slice()).ok().expect(MEMWRITER_ERROR);

        let output = writer.unwrap();
        assert_eq!(output.len(), ENTRY_SIZE);

        output
    }
}

/**
 * A collection of 8 hues
 */
pub struct HueGroup {
    ///Unknown usage
    pub header: u32,
    pub entries: [Hue, ..8]
}

impl HueGroup {

    pub fn new(header: u32, entries: [Hue, ..8]) -> HueGroup {
        HueGroup {
            header: header,
            entries: entries
        }
    }

    pub fn serialize(&self) -> Vec<u8> {
        let mut writer = MemWriter::new();
        writer.write_le_u32(self.header).ok().expect(MEMWRITER_ERROR);
        for hue in self.entries.iter() {
            writer.write(hue.serialize().as_slice()).ok().expect(MEMWRITER_ERROR);
        }
        writer.unwrap()
    }
}

//A hue_entry is (32 * 2) + 2 + 2 + 20 bytes = 88 bytes
const ENTRY_SIZE: uint = 88;
//8 entries to a group, plus a 4 byte header. 708 bytes.
const GROUP_SIZE: uint = (ENTRY_SIZE * 8) + 4;

pub struct HueReader {
    data_reader: File
}

impl HueReader {
    pub fn new(hues_path: &Path) -> IoResult<HueReader> {
        let data_reader = try!(File::open_mode(hues_path, Open, Read));

        Ok(HueReader {
            data_reader: data_reader
        })
    }

    /**
     * Read the given indexed group
     */
    pub fn read_hue_group(&mut self, id: u32) -> IoResult<HueGroup> {
        try!(self.data_reader.seek((id as uint * GROUP_SIZE) as i64, SeekSet));

        let header = try!(self.data_reader.read_le_u32());

        let entries: [Hue, ..8] = [
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue()),
            try!(self.read_hue())
        ];

        Ok(HueGroup {
            header: header,
            entries: entries
        })
    }

    fn read_hue(&mut self) -> IoResult<Hue> {
        let mut color_table = [0u16, ..32];
        for idx in range(0u, 32) {
            color_table[idx] = try!(self.data_reader.read_le_u16());
        }

        let table_start = try!(self.data_reader.read_le_u16());
        let table_end = try!(self.data_reader.read_le_u16());

        let raw_name = try!(self.data_reader.read_exact(20));

        //Slice it down into a normal string size
        let trimmed_name: Vec<u8> = raw_name.into_iter().take_while(|&element| element != 0).collect();

        let name = trimmed_name.into_ascii().into_string();

        Ok(Hue::new(
            color_table,
            table_start,
            table_end,
            name
        ))

    }
}
<|endoftext|>


<commit_before>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use gui::chars;
use util::units::{Direction, Point};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_location: Point,
    info_location: Point,
    message_location: Point,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_location: Point::new(16, 1),
                info_location: Point::new(1, 1),
                message_location: Point::new(16, 41),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        return None;
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.render_map(game, console);

        let repr = game.world.player.repr;
        let pos = game.world.player.pos;

        console.put_plain(self.map_location + pos, repr);

        self.draw_borders(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        console.put_plain(self.map_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.map_location + Point::new(63, -1), chars::NE as char);
        console.put_plain(self.map_location + Point::new(-1, 38), chars::SW as char);
        console.put_plain(self.map_location + Point::new(63, 38), chars::SE as char);

        for x in 0..63 {
            console.put_plain(self.map_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.map_location + Point::new(x, 38), chars::HLINE as char);
        }

        for y in 0..38 {
            console.put_plain(self.map_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.map_location + Point::new(63, y), chars::VLINE as char);
        }

        console.print_plain(self.map_location + Point::new(0, -1), "Map");

        console.put_plain(self.info_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.info_location + Point::new(13, -1), chars::NE as char);
        console.put_plain(self.info_location + Point::new(-1, 48), chars::SW as char);
        console.put_plain(self.info_location + Point::new(13, 48), chars::SE as char);

        for x in 0..13 {
            console.put_plain(self.info_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.info_location + Point::new(x, 48), chars::HLINE as char);
        }

        for y in 0..48 {
            console.put_plain(self.info_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.info_location + Point::new(13, y), chars::VLINE as char);
        }

        console.print_plain(self.info_location + Point::new(0, -1), "Info");

        console.put_plain(self.message_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.message_location + Point::new(63, -1), chars::NE as char);
        console.put_plain(self.message_location + Point::new(-1,  8), chars::SW as char);
        console.put_plain(self.message_location + Point::new(63,  8), chars::SE as char);

        for x in 0..63 {
            console.put_plain(self.message_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.message_location + Point::new(x,  8), chars::HLINE as char);
        }

        for y in 0..8 {
            console.put_plain(self.message_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.message_location + Point::new(63, y), chars::VLINE as char);
        }

        console.print_plain(self.message_location + Point::new(0, -1), "Messages");
    }

    #[allow(unused)]
    fn render_map(&self, game: &mut Game, console: &mut Console) {
        let map = &(game.world.map);

        for (y, line) in map.tiles.iter().enumerate() {
            for (x, cell) in line.iter().enumerate() {
                console.put(self.map_location + Point::new(x as i32, y as i32), ' ', Colors::white, cell.b_color());
            }
        }
    }

}
<commit_msg>Un-duplicate border-drawing code<commit_after>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use gui::chars;
use util::units::{Direction, Point};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_location: Point,
    info_location: Point,
    message_location: Point,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_location: Point::new(16, 1),
                info_location: Point::new(1, 1),
                message_location: Point::new(16, 41),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        return None;
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.render_map(game, console);

        let repr = game.world.player.repr;
        let pos = game.world.player.pos;

        console.put_plain(self.map_location + pos, repr);

        self.draw_borders(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        self.draw_box(console, self.map_location + Point::new(-1, -1), 64, 39);
        console.print_plain(self.map_location + Point::new(0, -1), "Map");

        self.draw_box(console, self.info_location + Point::new(-1, -1), 14, 49);
        console.print_plain(self.info_location + Point::new(0, -1), "Info");

        self.draw_box(console, self.message_location + Point::new(-1, -1), 64, 9);
        console.print_plain(self.message_location + Point::new(0, -1), "Messages");
    }

    fn draw_box(&self, console: &mut Console, loc: Point, width: i32, height: i32) {
        console.put_plain(loc + Point::new(0, 0), chars::NW as char);
        console.put_plain(loc + Point::new(width, 0), chars::NE as char);
        console.put_plain(loc + Point::new(0, height), chars::SW as char);
        console.put_plain(loc + Point::new(width, height), chars::SE as char);

        for x in 1..width {
            console.put_plain(loc + Point::new(x, 0), chars::HLINE as char);
            console.put_plain(loc + Point::new(x, height), chars::HLINE as char);
        }

        for y in 1..height {
            console.put_plain(loc + Point::new(0, y), chars::VLINE as char);
            console.put_plain(loc + Point::new(width, y), chars::VLINE as char);
        }
    }

    #[allow(unused)]
    fn render_map(&self, game: &mut Game, console: &mut Console) {
        let map = &(game.world.map);

        for (y, line) in map.tiles.iter().enumerate() {
            for (x, cell) in line.iter().enumerate() {
                console.put(self.map_location + Point::new(x as i32, y as i32), ' ', Colors::white, cell.b_color());
            }
        }
    }

}
<|endoftext|>


<commit_before>use bit_vec::BitVec;
use num::pow;
use std::slice::Iter;
use lfsr;

#[derive(PartialEq, Debug)]
pub struct FibonacciLFSR {
    state: BitVec,
    taps: Vec<usize>,
}

impl FibonacciLFSR {
    pub fn from_iter(iter: Iter<usize>) -> Self {
        let &len = iter.clone().max().unwrap();

        let state = BitVec::from_elem(len, true);

        let mut taps: Vec<usize> = iter.map(|&t| t).collect();
        taps.sort();
        taps.dedup();

        FibonacciLFSR { state: state, taps: taps, }
    }

    pub fn output(&self) -> bool {
        let len = self.state.len();
        self.state[len - 1]
    }

    pub fn step(&mut self) {
        let b = self.feedback_bit();

        self.shift();

        self.state.set(0, b);
    }

    fn shift(&mut self) {
        lfsr::shift(&mut self.state);
    }

    fn feedback_bit(&mut self) -> bool {
        self.taps
            .iter()
            .map(|&i| self.state[i-1])
            .fold(false, |acc, b| acc ^ b)
    }

    pub fn iter(&mut self) -> LFSRIter {
        LFSRIter { lfsr: self }
    }

    fn lsbyte(&self) -> u8 {
        self.state
            .iter()
            .take(8)
            .enumerate()
            .fold(0, |acc, (i, b)| acc + (b as u8) * pow(2, i))
    }

    pub fn bytes(&mut self) -> LFSRByteIter {
        if self.state.len() < 8 {
            panic!("LFSR must have length at least 8 to iterate bytes");
        }

        LFSRByteIter { lfsr: self }
    }
}

pub struct LFSRIter<'a> {
    lfsr: &'a mut FibonacciLFSR,
}

impl<'a> Iterator for LFSRIter<'a> {
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        let r = self.lfsr.state.get(0);
        self.lfsr.step();
        r
    }
}

pub struct LFSRByteIter<'a> {
    lfsr: &'a mut FibonacciLFSR,
}

impl<'a> Iterator for LFSRByteIter<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        let byte = self.lfsr.lsbyte();
        self.lfsr.step();
        Some(byte)
    }
}
<commit_msg>Add LFSR impl for FibonacciLFSR<commit_after>use bit_vec::BitVec;
use num::pow;
use std::slice::Iter;
use lfsr;

#[derive(PartialEq, Debug)]
pub struct FibonacciLFSR {
    state: BitVec,
    taps: Vec<usize>,
}

impl FibonacciLFSR {
    pub fn from_iter(iter: Iter<usize>) -> Self {
        let &len = iter.clone().max().unwrap();

        let state = BitVec::from_elem(len, true);

        let mut taps: Vec<usize> = iter.map(|&t| t).collect();
        taps.sort();
        taps.dedup();

        FibonacciLFSR { state: state, taps: taps, }
    }

    fn shift(&mut self) {
        lfsr::shift(&mut self.state);
    }

    fn feedback_bit(&mut self) -> bool {
        self.taps
            .iter()
            .map(|&i| self.state[i-1])
            .fold(false, |acc, b| acc ^ b)
    }

    pub fn iter(&mut self) -> LFSRIter {
        LFSRIter { lfsr: self }
    }

    fn lsbyte(&self) -> u8 {
        self.state
            .iter()
            .take(8)
            .enumerate()
            .fold(0, |acc, (i, b)| acc + (b as u8) * pow(2, i))
    }

    pub fn bytes(&mut self) -> LFSRByteIter {
        if self.state.len() < 8 {
            panic!("LFSR must have length at least 8 to iterate bytes");
        }

        LFSRByteIter { lfsr: self }
    }
}

impl lfsr::LFSR for FibonacciLFSR {
    fn output(&self) -> bool {
        let len = self.state.len();
        self.state[len - 1]
    }

    fn step(&mut self) {
        let b = self.feedback_bit();

        self.shift();

        self.state.set(0, b);
    }
}

pub struct LFSRIter<'a> {
    lfsr: &'a mut FibonacciLFSR,
}

impl<'a> Iterator for LFSRIter<'a> {
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        use lfsr::LFSR;
        let r = self.lfsr.state.get(0);
        self.lfsr.step();
        r
    }
}

pub struct LFSRByteIter<'a> {
    lfsr: &'a mut FibonacciLFSR,
}

impl<'a> Iterator for LFSRByteIter<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        use lfsr::LFSR;
        let byte = self.lfsr.lsbyte();
        self.lfsr.step();
        Some(byte)
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;
use std::path::Path;
use std::ops::{Deref, DerefMut};
use std::collections::HashMap;

use perlin_core::index::Index;
use perlin_core::index::posting::DocId;

use language::PipelineBucket;

mod filter;
mod hierarchy;

pub use field::filter::Filter;
pub use field::hierarchy::Hierarchy;

pub enum FieldSupplement<T> {
    None,
    Filter(Filter<T>),
    Hierarchy(Hierarchy<T>),
}

pub struct Field<T: Hash + Eq> {
    index: Index<T>,
    supplement: FieldSupplement<T>,
}

impl<T: Hash + Eq + Ord + Clone + 'static> Field<T> {
    pub fn commit(&mut self) {
        self.index.commit();

        if let FieldSupplement::Filter(ref mut filter) = self.supplement {
            filter.commit(&self.index);
        }
    }
}

impl<TTerm> PipelineBucket<TTerm> for Field<TTerm>
    where TTerm: Hash + Eq + Ord
{
    fn put(&mut self, doc_id: DocId, term: TTerm) {
        self.index.index_term(doc_id, term);
    }
}

impl<T: Hash + Eq> DerefMut for Field<T> {
    fn deref_mut(&mut self) -> &mut Index<T> {
        &mut self.index
    }
}

impl<T: Hash + Eq> Deref for Field<T> {
    type Target = Index<T>;
    fn deref(&self) -> &Index<T> {
        &self.index
    }
}

pub struct Fields<T: Hash + Eq> {
    fields: HashMap<String, Field<T>>,
}

impl<T: Hash + Eq + Ord> Fields<T> {
    pub fn commit(&mut self) {
        for field in self.fields.values_mut() {
            field.commit();
        }
    }

    pub fn add_field(&mut self,
                     name: String,
                     path: &Path,
                     supplement: FieldSupplement<T>)
                     -> Result<(), ()> {
        use perlin_core::page_manager::{RamPageCache, FsPageManager};
        use perlin_core::index::vocabulary::SharedVocabulary;
        use perlin_core::index::Index;
        if self.fields.contains_key(&name) {
            return Err(());
        } else {
            let page_cache =
                RamPageCache::new(FsPageManager::new(&path.join(format!("{}_page_cache", name))));
            self.fields.insert(name,
                               Field {
                                   index: Index::new(page_cache, SharedVocabulary::new()),
                                   supplement,
                               });
            return Ok(());
        }
    }

    pub fn new() -> Self {
        Fields { fields: HashMap::new() }
    }
}

#[cfg(test)]
mod tests {
    use perlin_core::index::posting::DocId;
    use field::{Fields};

    use rust_stemmers::Algorithm;

    #[derive(PerlinDocument)]
    pub struct FilterTest {
        body: Fields<String>,
    }
    // pub use self::perlin_impl::FilterTestIndex;
    // mod perlin_impl {
    //     use super::*;
    //     use std::path::{Path, PathBuf};
    //     use std::borrow::Cow;
    //     use document_index::Pipeline;
    //     use document_index::QueryPipeline;
    //     use document_index::QueryResultIterator;
    //     use query::Operand;
    //     use query::Query;
    //     use perlin_core::index::posting::{PostingIterator, DocId};
    //     use perlin_core::index::vocabulary::TermId;
    //     pub struct FilterTestIndex {
    //         pub documents: FilterTest,
    //         pub query_pipeline: Option<QueryPipeline<FilterTest>>,
    //         pub doc_counter: DocId,
    //     }
    //     impl FilterTestIndex {
    //         pub fn create(base_path: PathBuf) -> Self {
    //             FilterTestIndex {
    //                 documents: FilterTest::create(&base_path),
    //                 query_pipeline: None,
    //                 doc_counter: DocId::none(),
    //             }
    //         }
    //         pub fn commit(&mut self) {
    //             self.documents.commit();
    //         }
    // pub fn set_query_pipeline(&mut self, pipe:
    // QueryPipeline<FilterTest>) {
    //             self.query_pipeline = Some(pipe);
    //         }
    //         pub fn run_query<'a>(&'a self, query: Query<'a>) -> Operand<'a> {
    //             if let Some(ref query_pipe) = self.query_pipeline {
    //                 query_pipe(&self.documents, query)
    //             } else {
    //                 {
    //                     panic!()
    //                 };
    //             }
    //         }
    //     }
    //     impl FilterTest {
    //         pub fn create(path: &Path) -> Self {
    //             use perlin_core::page_manager::{RamPageCache, FsPageManager};
    //             use perlin_core::index::vocabulary::SharedVocabulary;
    //             use perlin_core::index::Index;
    //             let body_page_cache =
    //                 RamPageCache::new(
    // FsPageManager::new(&path.join("body_page_cache")));
    //             let number_page_cache =
    //                 RamPageCache::new(
    // FsPageManager::new(&path.join("number_page_cache")));
    //             FilterTest {
    //                 body: Index::new(body_page_cache, SharedVocabulary::new()),
    // number: FilterField::new(Index::new(number_page_cache,
    // SharedVocabulary::new())),
    //             }
    //         }
    //         pub fn commit(&mut self) {
    //             self.body.commit();
    //             self.number.commit();
    //         }
    //     }
    // }

}
<commit_msg>make fields public<commit_after>use std::hash::Hash;
use std::path::Path;
use std::ops::{Deref, DerefMut};
use std::collections::HashMap;

use perlin_core::index::Index;
use perlin_core::index::posting::DocId;

use language::PipelineBucket;

mod filter;
mod hierarchy;

pub use field::filter::Filter;
pub use field::hierarchy::Hierarchy;

pub enum FieldSupplement<T> {
    None,
    Filter(Filter<T>),
    Hierarchy(Hierarchy<T>),
}

pub struct Field<T: Hash + Eq> {
    index: Index<T>,
    supplement: FieldSupplement<T>,
}

impl<T: Hash + Eq + Ord + Clone + 'static> Field<T> {
    pub fn commit(&mut self) {
        self.index.commit();

        if let FieldSupplement::Filter(ref mut filter) = self.supplement {
            filter.commit(&self.index);
        }
    }
}

impl<TTerm> PipelineBucket<TTerm> for Field<TTerm>
    where TTerm: Hash + Eq + Ord
{
    fn put(&mut self, doc_id: DocId, term: TTerm) {
        self.index.index_term(doc_id, term);
    }
}

impl<T: Hash + Eq> DerefMut for Field<T> {
    fn deref_mut(&mut self) -> &mut Index<T> {
        &mut self.index
    }
}

impl<T: Hash + Eq> Deref for Field<T> {
    type Target = Index<T>;
    fn deref(&self) -> &Index<T> {
        &self.index
    }
}

pub struct Fields<T: Hash + Eq> {
    pub fields: HashMap<String, Field<T>>,
}

impl<T: Hash + Eq + Ord> Fields<T> {
    pub fn commit(&mut self) {
        for field in self.fields.values_mut() {
            field.commit();
        }
    }

    pub fn add_field(&mut self,
                     name: String,
                     path: &Path,
                     supplement: FieldSupplement<T>)
                     -> Result<(), ()> {
        use perlin_core::page_manager::{RamPageCache, FsPageManager};
        use perlin_core::index::vocabulary::SharedVocabulary;
        use perlin_core::index::Index;
        if self.fields.contains_key(&name) {
            return Err(());
        } else {
            let page_cache =
                RamPageCache::new(FsPageManager::new(&path.join(format!("{}_page_cache", name))));
            self.fields.insert(name,
                               Field {
                                   index: Index::new(page_cache, SharedVocabulary::new()),
                                   supplement,
                               });
            return Ok(());
        }
    }

    pub fn new() -> Self {
        Fields { fields: HashMap::new() }
    }
}

#[cfg(test)]
mod tests {
    use perlin_core::index::posting::DocId;
    use field::{Fields};

    use rust_stemmers::Algorithm;

    #[derive(PerlinDocument)]
    pub struct FilterTest {
        body: Fields<String>,
    }
    // pub use self::perlin_impl::FilterTestIndex;
    // mod perlin_impl {
    //     use super::*;
    //     use std::path::{Path, PathBuf};
    //     use std::borrow::Cow;
    //     use document_index::Pipeline;
    //     use document_index::QueryPipeline;
    //     use document_index::QueryResultIterator;
    //     use query::Operand;
    //     use query::Query;
    //     use perlin_core::index::posting::{PostingIterator, DocId};
    //     use perlin_core::index::vocabulary::TermId;
    //     pub struct FilterTestIndex {
    //         pub documents: FilterTest,
    //         pub query_pipeline: Option<QueryPipeline<FilterTest>>,
    //         pub doc_counter: DocId,
    //     }
    //     impl FilterTestIndex {
    //         pub fn create(base_path: PathBuf) -> Self {
    //             FilterTestIndex {
    //                 documents: FilterTest::create(&base_path),
    //                 query_pipeline: None,
    //                 doc_counter: DocId::none(),
    //             }
    //         }
    //         pub fn commit(&mut self) {
    //             self.documents.commit();
    //         }
    // pub fn set_query_pipeline(&mut self, pipe:
    // QueryPipeline<FilterTest>) {
    //             self.query_pipeline = Some(pipe);
    //         }
    //         pub fn run_query<'a>(&'a self, query: Query<'a>) -> Operand<'a> {
    //             if let Some(ref query_pipe) = self.query_pipeline {
    //                 query_pipe(&self.documents, query)
    //             } else {
    //                 {
    //                     panic!()
    //                 };
    //             }
    //         }
    //     }
    //     impl FilterTest {
    //         pub fn create(path: &Path) -> Self {
    //             use perlin_core::page_manager::{RamPageCache, FsPageManager};
    //             use perlin_core::index::vocabulary::SharedVocabulary;
    //             use perlin_core::index::Index;
    //             let body_page_cache =
    //                 RamPageCache::new(
    // FsPageManager::new(&path.join("body_page_cache")));
    //             let number_page_cache =
    //                 RamPageCache::new(
    // FsPageManager::new(&path.join("number_page_cache")));
    //             FilterTest {
    //                 body: Index::new(body_page_cache, SharedVocabulary::new()),
    // number: FilterField::new(Index::new(number_page_cache,
    // SharedVocabulary::new())),
    //             }
    //         }
    //         pub fn commit(&mut self) {
    //             self.body.commit();
    //             self.number.commit();
    //         }
    //     }
    // }

}
<|endoftext|>


<commit_before>use name::*;
use art::*;

/// Nominal, artful lists: Lists with names and articulation points
#[deriving(Show,Hash,PartialEq,Eq)]
pub enum List<T> {
    Nil,
    Cons(T, Box<List<T>>),
    Name(Name, Box<List<T>>),
    Art(Art<Box<List<T>>>)
}

pub fn copy<T>(list:List<T>) -> List<T>
where T:'static {
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons(hd, box copy(*tl)),
        List::Art(art)    => copy(*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box copy(*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn map<T,S,F> (f:&'static F, list:List<T>) -> List<S>
where T:'static, S:'static,
      F:Fn(T) -> S
{
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons((*f)(hd), box map(f,*tl)),
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => map(f,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box map(f,*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn contract<F,G,T> (f:&'static F, g:&'static G, list:List<T>) -> List<T>
where T:'static,
      F:Fn(&T,&T) -> bool,
      G:Fn(T,T) -> T
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd1, box list) => {
            match list {
                List::Nil => List::Cons(hd1, box List::Nil),
                List::Cons(hd2, tl) => {
                    if (*f)(&hd1,&hd2) {
                        List::Cons((*g)(hd1,hd2), box contract(f,g,*tl))
                    } else {
                        List::Cons(hd1, box contract(f, g, List::Cons(hd2, tl)))
                    } },
                // - - - - - boilerplate cases - - - - - -
                List::Art(art) => contract(f,g,List::Cons(hd1,force(art))),
                List::Name(nm, tl) => {
                    let (nm1,nm2) = fork(nm) ;
                    let art = nart!(nm1, box contract(f,g,List::Cons(hd1,tl))) ;
                    List::Name(nm2, box List::Art(art))
                }
            }
        },
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => contract(f,g,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box contract(f,g,*tl)) ;
            List::Name(nm2, box List::Art(art))
        },
    }
}

pub fn reduce<F,G,T> (f:&'static F, g:&'static G, list:List<T>) -> Option<T>
where T:'static,
      F: Fn(&T,&T) -> bool + 'static,
      G: Fn(T, T) -> T + 'static
{
    match list {
        List::Nil => None,
        List::Cons(hd, box list) => {
            match list {
                List::Nil => Some(hd),
                List::Cons(hd2, tl) => {
                    let hd3 = (*g)(hd,hd2) ;
                    let list = contract(f, g, List::Cons(hd3, tl)) ;
                    reduce (f, g, list)
                },
                // - - - - - boilerplate cases - - - - - -
                List::Name(_,tl) => reduce (f, g, *tl),
                List::Art(art) => reduce (f, g, *force(art)),
            }},
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => reduce(f, g, *force(art)),
        List::Name(_,tl) => reduce(f, g, *tl),
    }
}

pub fn merge<T,Ord> (ord:Ord, list1:List<T>, list2:List<T>) -> List<T>
where T:'static,
      Ord: Fn(&T,&T) -> bool + 'static
{
    match (list1, list2) {
        (List::Nil, list2) => list2,
        (list1, List::Nil) => list1,
        (List::Cons(hd1,tl1),
         List::Cons(hd2,tl2)) =>
            if ord(&hd1,&hd2) {
                List::Cons(hd1, box merge(ord, *tl1, List::Cons(hd2,tl2)))
            } else {
                List::Cons(hd2, box merge(ord, List::Cons(hd1,tl1), *tl2))
            },
        // - - - - - boilerplate cases - - - - -
        (List::Name(nm,tl), list2) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, *tl, list2)) ;
            List::Name(nm2, box List::Art(art))
        },
        (list1, List::Name(nm,tl)) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, list1, *tl)) ;
            List::Name(nm2, box List::Art(art))
        },
        (List::Art(art), list2) => merge(ord, *force(art), list2),
        (list1, List::Art(art)) => merge(ord, list1, *force(art)),
    }
}

#[test]
pub fn construct_list () {
    let z : List<int> = List::Nil;
    let y : List<int> = List::Cons(1, box z);
    let x : List<int> = List::Art(cell(symbol(format!("two")), box y));
    let l : List<int> = List::Name(symbol(format!("one")), box x);
    println!("constructed list: {}", l);
}

// impl<T> List<T> {
//     /// Construct a new, empty list.
//     #[inline]
//     pub fn new() -> List<T> { Nil }
// }

// impl<T: Send + Sync> List<T> {
//     /// Create a list with one element in it.
//     #[inline]
//     pub fn singleton(n:Name,val: T) -> List<T> { Cons(val, Art::new(Nil)) }

//     /// Get the head of a list.
//     pub fn head(&self) -> Option<&T> {
//         match *self {
//             Nil => None,
//             Cons(ref head, _) => Some(head)
//         }
//     }

//     /// Get the tail of a list.
//     pub fn tail(&self) -> Option<Art<List<T>>> {
//         match *self {
//             Nil => None,
//             Cons(_, ref tail) => Some(tail.clone())
//         }
//     }

//     /// Get an iterator over the items in a list.
//     pub fn iter<'a>(&'a self) -> ListItems<'a, T> {
//         ListItems {
//             list: self
//         }
//     }
// }

// /// An iterator over the items in a list.
// pub struct ListItems<'a, T: 'a> {
//     list: &'a List<T>
// }

// impl<'a, T: Send + Sync> Iterator<&'a T> for ListItems<'a, T> {
//     fn next(&mut self) -> Option<&'a T> {
//         match *self.list {
//             Cons(ref head, ref tail) => {
//                 self.list = &**tail;
//                 Some(head)
//             },
//             Nil => None
//         }
//     }
// }

<commit_msg>triggered internal Rust compiler bug<commit_after>use name::*;
use art::*;

/// Nominal, artful lists: Lists with names and articulation points
#[deriving(Show,Hash,PartialEq,Eq)]
pub enum List<T> {
    Nil,
    Cons(T, Box<List<T>>),
    Name(Name, Box<List<T>>),
    Art(Art<Box<List<T>>>)
}

pub fn copy<T>(list:List<T>) -> List<T>
where T:'static {
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons(hd, box copy(*tl)),
        List::Art(art)    => copy(*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box copy(*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn map<T,S,F> (f:&'static F, list:List<T>) -> List<S>
where T:'static, S:'static,
      F:Fn(T) -> S
{
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons((*f)(hd), box map(f,*tl)),
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => map(f,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box map(f,*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn contract<F,G,T> (f:&'static F, g:&'static G, list:List<T>) -> List<T>
where T:'static,
      F:Fn(&T,&T) -> bool,
      G:Fn(T,T) -> T
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd1, box list) => {
            match list {
                List::Nil => List::Cons(hd1, box List::Nil),
                List::Cons(hd2, tl) => {
                    if (*f)(&hd1,&hd2) {
                        List::Cons((*g)(hd1,hd2), box contract(f,g,*tl))
                    } else {
                        List::Cons(hd1, box contract(f, g, List::Cons(hd2, tl)))
                    } },
                // - - - - - boilerplate cases - - - - - -
                List::Art(art) => contract(f,g,List::Cons(hd1,force(art))),
                List::Name(nm, tl) => {
                    let (nm1,nm2) = fork(nm) ;
                    let art = nart!(nm1, box contract(f,g,List::Cons(hd1,tl))) ;
                    List::Name(nm2, box List::Art(art))
                }
            }
        },
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => contract(f,g,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box contract(f,g,*tl)) ;
            List::Name(nm2, box List::Art(art))
        },
    }
}

pub fn reduce<F,G,T> (f:&'static F, g:&'static G, list:List<T>) -> Option<T>
where T:'static,
      F: Fn(&T,&T) -> bool + 'static,
      G: Fn(T, T) -> T + 'static
{
    match list {
        List::Nil => None,
        List::Cons(hd, box list) => {
            match list {
                List::Nil => Some(hd),
                List::Cons(hd2, tl) => {
                    let hd3 = (*g)(hd,hd2) ;
                    let list = contract(f, g, List::Cons(hd3, tl)) ;
                    reduce (f, g, list)
                },
                // - - - - - boilerplate cases - - - - - -
                List::Name(_,tl) => reduce (f, g, *tl),
                List::Art(art)   => reduce (f, g, *force(art)),
            }},
        // - - - - - boilerplate cases - - - - - -
        List::Name(_,tl) => reduce(f, g, *tl),
        List::Art(art)   => reduce(f, g, *force(art)),
    }
}

pub fn merge<T,Ord> (ord:Ord, list1:List<T>, list2:List<T>) -> List<T>
where T:'static,
      Ord: Fn(&T,&T) -> bool + 'static
{
    match (list1, list2) {
        (List::Nil, list2) => list2,
        (list1, List::Nil) => list1,
        (List::Cons(hd1,tl1),
         List::Cons(hd2,tl2)) =>
            if ord(&hd1,&hd2) {
                List::Cons(hd1, box merge(ord, *tl1, List::Cons(hd2,tl2)))
            } else {
                List::Cons(hd2, box merge(ord, List::Cons(hd1,tl1), *tl2))
            },
        // - - - - - boilerplate cases - - - - -
        (List::Name(nm,tl), list2) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, *tl, list2)) ;
            List::Name(nm2, box List::Art(art))
        },
        (list1, List::Name(nm,tl)) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, list1, *tl)) ;
            List::Name(nm2, box List::Art(art))
        },
        (List::Art(art), list2) => merge(ord, *force(art), list2),
        (list1, List::Art(art)) => merge(ord, list1, *force(art)),
    }
}

pub fn singletons<T> (list:List<T>) -> List<List<T>>
where T: 'static
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd, tl) => {
            List::Cons( List::Cons(hd, box List::Nil),
                        box singletons(*tl) )
        },
        List::Art(art) => singletons(*force(art)),
        List::Name(nm, tl) => {
            let (nm1, nm2) = fork(nm) ;
            let art = nart!(nm2, box singletons(*tl)) ;
            List::Name(nm1, box List::Art(art))
        }
    }
}

 pub fn mergesort<F,G,T> (ord:&'static Ord, list:List<T>) -> List<T>
  where T: 'static,
        Ord: Fn(&List<T>, &List<T>) -> bool + 'static,
 {
     let c = |list1:List<T>,list2:List<T>| false ; // TODO
     let m = |list1:List<T>,list2:List<T>| merge(ord,list1,list2) ;
     let r = reduce(&c, &m, singletons(list)) ;
     match r {
         None => List::Nil,
         Some(list) => list
     }
 }

#[test]
pub fn construct_list () {
    let z : List<int> = List::Nil;
    let y : List<int> = List::Cons(1, box z);
    let x : List<int> = List::Art(cell(symbol(format!("two")), box y));
    let l : List<int> = List::Name(symbol(format!("one")), box x);
    println!("constructed list: {}", l);
}

// impl<T> List<T> {
//     /// Construct a new, empty list.
//     #[inline]
//     pub fn new() -> List<T> { Nil }
// }

// impl<T: Send + Sync> List<T> {
//     /// Create a list with one element in it.
//     #[inline]
//     pub fn singleton(n:Name,val: T) -> List<T> { Cons(val, Art::new(Nil)) }

//     /// Get the head of a list.
//     pub fn head(&self) -> Option<&T> {
//         match *self {
//             Nil => None,
//             Cons(ref head, _) => Some(head)
//         }
//     }

//     /// Get the tail of a list.
//     pub fn tail(&self) -> Option<Art<List<T>>> {
//         match *self {
//             Nil => None,
//             Cons(_, ref tail) => Some(tail.clone())
//         }
//     }

//     /// Get an iterator over the items in a list.
//     pub fn iter<'a>(&'a self) -> ListItems<'a, T> {
//         ListItems {
//             list: self
//         }
//     }
// }

// /// An iterator over the items in a list.
// pub struct ListItems<'a, T: 'a> {
//     list: &'a List<T>
// }

// impl<'a, T: Send + Sync> Iterator<&'a T> for ListItems<'a, T> {
//     fn next(&mut self) -> Option<&'a T> {
//         match *self.list {
//             Cons(ref head, ref tail) => {
//                 self.list = &**tail;
//                 Some(head)
//             },
//             Nil => None
//         }
//     }
// }

<|endoftext|>


<commit_before>extern crate libc;
extern crate std;

use super::liblua;
use super::Index;
use super::Lua;
use super::Pushable;
use super::Readable;

unsafe extern fn wrapper(lua: *mut liblua::lua_State) -> libc::c_int {
    /*const auto toCall = static_cast<TFunctionObject*>(lua_touserdata(state, lua_upvalueindex(1)));
    return callback(state, toCall, lua_gettop(state)).release();*/
    0
}

impl<TRetValue: Pushable> Pushable for proc() -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
    }
}

impl<TRetValue: Pushable> Pushable for fn() -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
    }
}

impl<TParam1: Readable, TRetValue: Pushable> Pushable for fn(TParam1) -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
        //unsafe { liblua::lua_pushinteger(lua.lua, self) }
    }
}

<commit_msg>Fixed another compilation error<commit_after>extern crate libc;
extern crate std;

use super::liblua;
use super::Index;
use super::Lua;
use super::Pushable;
use super::Readable;

extern fn wrapper(lua: *mut liblua::lua_State) -> libc::c_int {
    /*const auto toCall = static_cast<TFunctionObject*>(lua_touserdata(state, lua_upvalueindex(1)));
    return callback(state, toCall, lua_gettop(state)).release();*/
    0
}

impl<TRetValue: Pushable> Pushable for proc() -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
    }
}

impl<TRetValue: Pushable> Pushable for fn() -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
    }
}

impl<TParam1: Readable, TRetValue: Pushable> Pushable for fn(TParam1) -> TRetValue {
    fn push_to_lua(self, lua: &Lua) {
        //unsafe { liblua::lua_pushinteger(lua.lua, self) }
    }
}

<|endoftext|>


<commit_before>use calx::color;
use calx::Context;
use calx::event;
use calx::key;
use world;
use world::action;
use world::action::{Step};
use world::dir6::*;
use super::{State, Transition};
use worldview;
use titlestate::TitleState;

pub struct GameState;

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);
        let camera = world::camera();
        worldview::draw_world(&camera, ctx);

        if action::control_state() == action::ReadyToUpdate {
            action::update();
        }
    }

    /// Process a player control keypress.
    pub fn process_key(&mut self, key: key::Key) -> bool {
        if action::control_state() != action::AwaitingInput {
            return false;
        }

        match key {
            key::KeyQ | key::KeyPad7 => { action::input(Step(NorthWest)); }
            key::KeyW | key::KeyPad8 | key::KeyUp => { action::input(Step(North)); }
            key::KeyE | key::KeyPad9 => { action::input(Step(NorthEast)); }
            key::KeyA | key::KeyPad1 => { action::input(Step(SouthWest)); }
            key::KeyS | key::KeyPad2 | key::KeyDown => { action::input(Step(South)); }
            key::KeyD | key::KeyPad3 => { action::input(Step(SouthEast)); }
            _ => { return false; }
        }
        return true;
    }
}

impl State for GameState {
    fn process(&mut self, event: event::Event) -> Option<Transition> {
        match event {
            event::Render(ctx) => {
                self.update(ctx);
            }
            event::KeyPressed(key::KeyEscape) => {
                return Some(super::NewState(box TitleState::new()));
            }
            event::KeyPressed(k) => {
                self.process_key(k);
            }
            _ => ()
        }
        None
    }
}
<commit_msg>FPS display<commit_after>use calx::color;
use calx::Context;
use calx::event;
use calx::key;
use calx::{Fonter, V2};
use world;
use world::action;
use world::action::{Step};
use world::dir6::*;
use super::{State, Transition};
use worldview;
use titlestate::TitleState;

pub struct GameState;

impl GameState {
    pub fn new(seed: Option<u32>) -> GameState {
        world::init_world(seed);
        GameState
    }

    /// Repaint view, update game world if needed.
    pub fn update(&mut self, ctx: &mut Context) {
        ctx.clear(&color::BLACK);
        let camera = world::camera();
        worldview::draw_world(&camera, ctx);
        let fps = 1.0 / ctx.render_duration;
        let _ = write!(&mut ctx.text_writer(V2(0, 8), 0.1, color::LIGHTGREEN)
                       .set_border(color::BLACK),
                       "FPS {}", fps);

        if action::control_state() == action::ReadyToUpdate {
            action::update();
        }
    }

    /// Process a player control keypress.
    pub fn process_key(&mut self, key: key::Key) -> bool {
        if action::control_state() != action::AwaitingInput {
            return false;
        }

        match key {
            key::KeyQ | key::KeyPad7 => { action::input(Step(NorthWest)); }
            key::KeyW | key::KeyPad8 | key::KeyUp => { action::input(Step(North)); }
            key::KeyE | key::KeyPad9 => { action::input(Step(NorthEast)); }
            key::KeyA | key::KeyPad1 => { action::input(Step(SouthWest)); }
            key::KeyS | key::KeyPad2 | key::KeyDown => { action::input(Step(South)); }
            key::KeyD | key::KeyPad3 => { action::input(Step(SouthEast)); }
            _ => { return false; }
        }
        return true;
    }
}

impl State for GameState {
    fn process(&mut self, event: event::Event) -> Option<Transition> {
        match event {
            event::Render(ctx) => {
                self.update(ctx);
            }
            event::KeyPressed(key::KeyEscape) => {
                return Some(super::NewState(box TitleState::new()));
            }
            event::KeyPressed(k) => {
                self.process_key(k);
            }
            _ => ()
        }
        None
    }
}
<|endoftext|>