<commit_before>//! Code for the internal Lua thread which handles all Lua requests.

use std::thread;
use std::fs::{File};
use std::path::Path;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::sync::{Mutex, RwLock};
use std::sync::mpsc::{channel, Sender, Receiver};

use hlua::{Lua, LuaError, functions_read};

use super::types::*;
use super::rust_interop;
use super::init_path;
use super::super::keys;

use ::layout::{try_lock_tree, ContainerType};

lazy_static! {
    /// Sends requests to the Lua thread
    static ref SENDER: Mutex<Option<Sender<LuaMessage>>> = Mutex::new(None);

    /// Whether the Lua thread is currently running
    pub static ref RUNNING: RwLock<bool> = RwLock::new(false);
}

pub const ERR_LOCK_RUNNING: &'static str = "Lua thread: unable to lock RUNNING";
pub const ERR_LOCK_SENDER: &'static str = "Lua thread: unable to lock SENDER";

const INIT_LUA_FUNC: &'static str = "way_cooler_init";
const LUA_TERMINATE_CODE: &'static str = "way_cooler.handle_termination()";
const LUA_RESTART_CODE: &'static str = "way_cooler.handle_restart()";

/// Struct sent to the Lua query
struct LuaMessage {
    reply: Sender<LuaResponse>,
    query: LuaQuery
}

unsafe impl Send for LuaMessage { }
unsafe impl Sync for LuaMessage { }

impl Debug for LuaMessage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "LuaMessage({:?})", self.query)
    }
}

// Reexported in lua/mod.rs:11
/// Whether the Lua thread is currently available.
pub fn running() -> bool {
    *RUNNING.read().expect(ERR_LOCK_RUNNING)
}

// Reexported in lua/mod.rs:11
/// Errors which may arise from attempting
/// to sending a message to the Lua thread.
#[derive(Debug)]
pub enum LuaSendError {
    /// The thread crashed, was shut down, or rebooted.
    ThreadClosed,
    /// The thread has not been initialized yet (maybe not used)
    ThreadUninitialized,
    /// The sender had an issue, most likey because the thread panicked.
    /// Following the `Sender` API, the original value sent is returned.
    Sender(LuaQuery)
}

// Reexported in lua/mod.rs:11
/// Attemps to send a LuaQuery to the Lua thread.
pub fn send(query: LuaQuery) -> Result<Receiver<LuaResponse>, LuaSendError> {
    if !running() {
        return Err(LuaSendError::ThreadClosed);
    }
    let thread_sender: Sender<LuaMessage>;
    {
        let maybe_sender = SENDER.lock().expect(ERR_LOCK_SENDER);
        match *maybe_sender {
            Some(ref real_sender) => {
                // Senders are designed to be cloneable
                thread_sender = real_sender.clone();
            },
            // If the sender doesn't exist yet, the thread doesn't either
            None => {
                return Err(LuaSendError::ThreadUninitialized);
            }
        }
    }
    // Create a response channel
    let (response_tx, response_rx) = channel();
    let message = LuaMessage { reply: response_tx, query: query };
    match thread_sender.send(message) {
        Ok(_) => Ok(response_rx),
        Err(e) => Err(LuaSendError::Sender(e.0.query))
    }
}

/// Initialize the Lua thread.
pub fn init() {
    debug!("Initializing...");
    let (tx, receiver) = channel();
    *SENDER.lock().expect(ERR_LOCK_SENDER) = Some(tx);
    let mut lua = Lua::new();
    debug!("Loading Lua libraries...");
    lua.openlibs();
    debug!("Loading way-cooler libraries...");
    rust_interop::register_libraries(&mut lua);

    let (use_config, maybe_init_file) = init_path::get_config();
    if use_config {
        match maybe_init_file {
            Ok(init_file) => {
                let _: () = lua.execute_from_reader(init_file)
                    .expect("Unable to load init file");
                debug!("Read init.lua successfully");
            }
            Err(_) => {
                debug!("Defaulting to pre-compiled init.lua");
                let _: () = lua.execute(init_path::DEFAULT_CONFIG)
                    .expect("Unable to load pre-compiled init file");
            }
        }
    }
    else {
        info!("Skipping config search");
    }

    // Call the special init hook function that we read from the init file
    lua.get(INIT_LUA_FUNC)
        .map(|mut f: functions_read::LuaFunction<_>|  f.call().unwrap_or_else(|err| {
            error!("Lua function \"{}\" returned an error: {:?}", INIT_LUA_FUNC, err);
        }));

    // Re-tile the layout tree, to make any changes appear immediantly.
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Root)
            .unwrap_or_else(|_| {
                warn!("Lua thread could not re-tile the layout tree");
            })
    }

    // Only ready after loading libs
    *RUNNING.write().expect(ERR_LOCK_RUNNING) = true;
    debug!("Entering main loop...");
    let _lua_handle = thread::Builder::new()
        .name("Lua thread".to_string())
        .spawn(move || { main_loop(receiver, &mut lua) });
}

/// Main loop of the Lua thread:
///
/// ## Loop
/// * Wait for a message from the receiver
/// * Handle message
/// * Send response
fn main_loop(receiver: Receiver<LuaMessage>, lua: &mut Lua) {
    loop {
        trace!("Lua: awaiting request");
        let request = receiver.recv();
        match request {
            Err(e) => {
                error!("Lua thread: unable to receive message: {}", e);
                error!("Lua thread: now panicking!");
                *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;

                panic!("Lua thread: lost contact with host, exiting!");
            }
            Ok(message) => {
                trace!("Handling a request");
                if !handle_message(message, lua) {
                    return
                }
            }
        }
    }
}

/// Handle each LuaQuery option sent to the thread
fn handle_message(request: LuaMessage, lua: &mut Lua) -> bool {
    match request.query {
        LuaQuery::Terminate => {
            trace!("Received terminate signal");
            if let Err(error) = lua.execute::<()>(LUA_TERMINATE_CODE) {
                error!("Lua termination callback returned an error: {:?}", error);
            }
            *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;
            thread_send(request.reply, LuaResponse::Pong);

            info!("Lua thread terminating!");
            return false
        },
        LuaQuery::Restart => {
            trace!("Received restart signal!");
            if let Err(error) = lua.execute::<()>(LUA_RESTART_CODE) {
                error!("Lua restart callback returned an error: {:?}", error);
            }
            *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;
            thread_send(request.reply, LuaResponse::Pong);

            // The only real way to restart
            let _new_handle = thread::Builder::new()
                .name("Lua re-init".to_string())
                .spawn(move || {
                    init();
                    keys::init();
                });

            info!("Lua thread restarting");
            return false
        },
        LuaQuery::Execute(code) => {
            trace!("Received request to execute {}", code);

            match lua.execute::<()>(&code) {
                Err(error) => {
                    warn!("Error executing code: {:?}", error);
                    thread_send(request.reply, LuaResponse::Error(error));
                }
                Ok(_) => {
                    trace!("Code executed okay.");
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
        },
        LuaQuery::ExecFile(name) => {
            info!("Executing {}", name);

            let path = Path::new(&name);
            let try_file = File::open(path);

            if let Ok(file) = try_file {
                let result = lua.execute_from_reader::<(), File>(file);
                if let Err(err) = result {
                    warn!("Error executing {}!", name);
                    thread_send(request.reply, LuaResponse::Error(err));
                }
                else {
                    trace!("Execution of {} successful.", name);
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
            else { // Could not open file
                // Unwrap_err is used because we're in the else of let Ok
                let read_error =
                    LuaError::ReadError(try_file.unwrap_err());
                thread_send(request.reply, LuaResponse::Error(read_error));
            }
        },
        LuaQuery::ExecRust(func) => {
            let result = func(lua);
            thread_send(request.reply, LuaResponse::Variable(Some(result)));
        },
        LuaQuery::HandleKey(press) => {
            trace!("Lua: handling keypress {}", &press);
            let press_ix = press.get_lua_index_string();
            // Access the index
            let code = format!("__key_map['{}']()", press_ix);
            match lua.execute::<()>(&code) {
                Err(error) => {
                    warn!("Error handling {}: {:?}", &press, error);
                    thread_send(request.reply, LuaResponse::Error(error));
                }
                Ok(_) => {
                    trace!("Handled keypress okay.");
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
        }
        LuaQuery::Ping => {
            thread_send(request.reply, LuaResponse::Pong);
        },
    }
    return true
}

fn thread_send(sender: Sender<LuaResponse>, response: LuaResponse) {
    match sender.send(response) {
        Err(err) => {
            match err.0 {
                LuaResponse::Pong => {}, // Those are boring
                _ => {
                    warn!("thread: Someone dropped an important Lua response!");
                }
            }
        }
        Ok(_) => {}
    }
}
<commit_msg>If init fails, defaults to compiled-in init file<commit_after>//! Code for the internal Lua thread which handles all Lua requests.

use std::thread;
use std::fs::{File};
use std::path::Path;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::sync::{Mutex, RwLock};
use std::sync::mpsc::{channel, Sender, Receiver};

use hlua::{Lua, LuaError, functions_read};

use super::types::*;
use super::rust_interop;
use super::init_path;
use super::super::keys;

use ::layout::{try_lock_tree, ContainerType};

lazy_static! {
    /// Sends requests to the Lua thread
    static ref SENDER: Mutex<Option<Sender<LuaMessage>>> = Mutex::new(None);

    /// Whether the Lua thread is currently running
    pub static ref RUNNING: RwLock<bool> = RwLock::new(false);
}

pub const ERR_LOCK_RUNNING: &'static str = "Lua thread: unable to lock RUNNING";
pub const ERR_LOCK_SENDER: &'static str = "Lua thread: unable to lock SENDER";

const INIT_LUA_FUNC: &'static str = "way_cooler_init";
const LUA_TERMINATE_CODE: &'static str = "way_cooler.handle_termination()";
const LUA_RESTART_CODE: &'static str = "way_cooler.handle_restart()";

/// Struct sent to the Lua query
struct LuaMessage {
    reply: Sender<LuaResponse>,
    query: LuaQuery
}

unsafe impl Send for LuaMessage { }
unsafe impl Sync for LuaMessage { }

impl Debug for LuaMessage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "LuaMessage({:?})", self.query)
    }
}

// Reexported in lua/mod.rs:11
/// Whether the Lua thread is currently available.
pub fn running() -> bool {
    *RUNNING.read().expect(ERR_LOCK_RUNNING)
}

// Reexported in lua/mod.rs:11
/// Errors which may arise from attempting
/// to sending a message to the Lua thread.
#[derive(Debug)]
pub enum LuaSendError {
    /// The thread crashed, was shut down, or rebooted.
    ThreadClosed,
    /// The thread has not been initialized yet (maybe not used)
    ThreadUninitialized,
    /// The sender had an issue, most likey because the thread panicked.
    /// Following the `Sender` API, the original value sent is returned.
    Sender(LuaQuery)
}

// Reexported in lua/mod.rs:11
/// Attemps to send a LuaQuery to the Lua thread.
pub fn send(query: LuaQuery) -> Result<Receiver<LuaResponse>, LuaSendError> {
    if !running() {
        return Err(LuaSendError::ThreadClosed);
    }
    let thread_sender: Sender<LuaMessage>;
    {
        let maybe_sender = SENDER.lock().expect(ERR_LOCK_SENDER);
        match *maybe_sender {
            Some(ref real_sender) => {
                // Senders are designed to be cloneable
                thread_sender = real_sender.clone();
            },
            // If the sender doesn't exist yet, the thread doesn't either
            None => {
                return Err(LuaSendError::ThreadUninitialized);
            }
        }
    }
    // Create a response channel
    let (response_tx, response_rx) = channel();
    let message = LuaMessage { reply: response_tx, query: query };
    match thread_sender.send(message) {
        Ok(_) => Ok(response_rx),
        Err(e) => Err(LuaSendError::Sender(e.0.query))
    }
}

/// Initialize the Lua thread.
pub fn init() {
    debug!("Initializing...");
    let (tx, receiver) = channel();
    *SENDER.lock().expect(ERR_LOCK_SENDER) = Some(tx);
    let mut lua = Lua::new();
    debug!("Loading Lua libraries...");
    lua.openlibs();
    debug!("Loading way-cooler libraries...");
    rust_interop::register_libraries(&mut lua);

    let (use_config, maybe_init_file) = init_path::get_config();
    if use_config {
        match maybe_init_file {
            Ok(init_file) => {
                let _: () = lua.execute_from_reader(init_file)
                    .map(|r| { debug!("Read init.lua successfully"); r })
                    .or_else(|_| lua.execute(init_path::DEFAULT_CONFIG))
                    .expect("Unable to load pre-compiled init file");
                debug!("Read init.lua successfully");
            }
            Err(_) => {
                debug!("Defaulting to pre-compiled init.lua");
                let _: () = lua.execute(init_path::DEFAULT_CONFIG)
                    .expect("Unable to load pre-compiled init file");
            }
        }
    }
    else {
        info!("Skipping config search");
    }

    // Call the special init hook function that we read from the init file
    lua.get(INIT_LUA_FUNC)
        .map(|mut f: functions_read::LuaFunction<_>|  f.call().unwrap_or_else(|err| {
            error!("Lua function \"{}\" returned an error: {:?}", INIT_LUA_FUNC, err);
        }));

    // Re-tile the layout tree, to make any changes appear immediantly.
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Root)
            .unwrap_or_else(|_| {
                warn!("Lua thread could not re-tile the layout tree");
            })
    }

    // Only ready after loading libs
    *RUNNING.write().expect(ERR_LOCK_RUNNING) = true;
    debug!("Entering main loop...");
    let _lua_handle = thread::Builder::new()
        .name("Lua thread".to_string())
        .spawn(move || { main_loop(receiver, &mut lua) });
}

/// Main loop of the Lua thread:
///
/// ## Loop
/// * Wait for a message from the receiver
/// * Handle message
/// * Send response
fn main_loop(receiver: Receiver<LuaMessage>, lua: &mut Lua) {
    loop {
        trace!("Lua: awaiting request");
        let request = receiver.recv();
        match request {
            Err(e) => {
                error!("Lua thread: unable to receive message: {}", e);
                error!("Lua thread: now panicking!");
                *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;

                panic!("Lua thread: lost contact with host, exiting!");
            }
            Ok(message) => {
                trace!("Handling a request");
                if !handle_message(message, lua) {
                    return
                }
            }
        }
    }
}

/// Handle each LuaQuery option sent to the thread
fn handle_message(request: LuaMessage, lua: &mut Lua) -> bool {
    match request.query {
        LuaQuery::Terminate => {
            trace!("Received terminate signal");
            if let Err(error) = lua.execute::<()>(LUA_TERMINATE_CODE) {
                error!("Lua termination callback returned an error: {:?}", error);
            }
            *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;
            thread_send(request.reply, LuaResponse::Pong);

            info!("Lua thread terminating!");
            return false
        },
        LuaQuery::Restart => {
            trace!("Received restart signal!");
            if let Err(error) = lua.execute::<()>(LUA_RESTART_CODE) {
                error!("Lua restart callback returned an error: {:?}", error);
            }
            *RUNNING.write().expect(ERR_LOCK_RUNNING) = false;
            thread_send(request.reply, LuaResponse::Pong);

            // The only real way to restart
            let _new_handle = thread::Builder::new()
                .name("Lua re-init".to_string())
                .spawn(move || {
                    init();
                    keys::init();
                });

            info!("Lua thread restarting");
            return false
        },
        LuaQuery::Execute(code) => {
            trace!("Received request to execute {}", code);

            match lua.execute::<()>(&code) {
                Err(error) => {
                    warn!("Error executing code: {:?}", error);
                    thread_send(request.reply, LuaResponse::Error(error));
                }
                Ok(_) => {
                    trace!("Code executed okay.");
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
        },
        LuaQuery::ExecFile(name) => {
            info!("Executing {}", name);

            let path = Path::new(&name);
            let try_file = File::open(path);

            if let Ok(file) = try_file {
                let result = lua.execute_from_reader::<(), File>(file);
                if let Err(err) = result {
                    warn!("Error executing {}!", name);
                    thread_send(request.reply, LuaResponse::Error(err));
                }
                else {
                    trace!("Execution of {} successful.", name);
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
            else { // Could not open file
                // Unwrap_err is used because we're in the else of let Ok
                let read_error =
                    LuaError::ReadError(try_file.unwrap_err());
                thread_send(request.reply, LuaResponse::Error(read_error));
            }
        },
        LuaQuery::ExecRust(func) => {
            let result = func(lua);
            thread_send(request.reply, LuaResponse::Variable(Some(result)));
        },
        LuaQuery::HandleKey(press) => {
            trace!("Lua: handling keypress {}", &press);
            let press_ix = press.get_lua_index_string();
            // Access the index
            let code = format!("__key_map['{}']()", press_ix);
            match lua.execute::<()>(&code) {
                Err(error) => {
                    warn!("Error handling {}: {:?}", &press, error);
                    thread_send(request.reply, LuaResponse::Error(error));
                }
                Ok(_) => {
                    trace!("Handled keypress okay.");
                    thread_send(request.reply, LuaResponse::Pong);
                }
            }
        }
        LuaQuery::Ping => {
            thread_send(request.reply, LuaResponse::Pong);
        },
    }
    return true
}

fn thread_send(sender: Sender<LuaResponse>, response: LuaResponse) {
    match sender.send(response) {
        Err(err) => {
            match err.0 {
                LuaResponse::Pong => {}, // Those are boring
                _ => {
                    warn!("thread: Someone dropped an important Lua response!");
                }
            }
        }
        Ok(_) => {}
    }
}
<|endoftext|>


<commit_before>

// #[cfg(debug_assertions)]
#[macro_use]
macro_rules! debug {
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[debug][{}:{}] {}: {}\n"
              , file!(), line!()
              , module_path!()
              , format_args!($($args)*)); }
    }
}

#[macro_use]
macro_rules! info {
    ( dots: $dots:expr, $msg:expr, status: $status:expr ) => {
        use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {} {}"
              , module_path!()
              , $msg, $status);
        print!("{:<38}{:>40}", concat!($dots, $msg), $status );
    };
    ( dots: $dots:expr, $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {}"
              , module_path!()
              , format_args!($($args)*));
        print!("{}{}", $dots, format_args!($($args)*)); }
    };
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {}"
              , module_path!()
              , format_args!($($args)*));
        print!( $($args)* ); }
    };
}

#[macro_use]
macro_rules! infoln {
    ( dots: $dots:expr, $msg:expr, status: $status:expr ) => {
        use core::fmt::Write;
        // TODO: only do this if we're in debug mode?

        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {} {}\n"
              , module_path!()
              , $msg, $status);
        println!("{:<38}{:>40}", concat!($dots, $msg), $status );
    };
    ( dots: $dots:expr, $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {}\n"
              , module_path!()
              , format_args!($($args)*));
        println!("{}{}", $dots, format_args!($($args)*)); }
    };
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        write!( $crate::arch::drivers::serial::COM1.lock()
              , "[info] {}: {}\n"
              , module_path!()
              , format_args!($($args)*));
        println!( $($args)* ); }
    };
}
<commit_msg>[kernel] suppress warnings in log macros<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Macros for kernel-level logging

// #[cfg(debug_assertions)]
#[macro_use]
macro_rules! debug {
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[debug][{}:{}] {}: {}\n"
                      , file!(), line!()
                      , module_path!()
                      , format_args!($($args)*)); }
    }
}

#[macro_use]
macro_rules! info {
    ( dots: $dots:expr, $msg:expr, status: $status:expr ) => {
        use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {} {}"
                      , module_path!()
                      , $msg, $status);
        print!("{:<38}{:>40}", concat!($dots, $msg), $status );
    };
    ( dots: $dots:expr, $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {}"
                      , module_path!()
                      , format_args!($($args)*));
        print!("{}{}", $dots, format_args!($($args)*)); }
    };
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {}"
                      , module_path!()
                      , format_args!($($args)*));
        print!( $($args)* ); }
    };
}

#[macro_use]
macro_rules! infoln {
    ( dots: $dots:expr, $msg:expr, status: $status:expr ) => {
        use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {} {}\n"
                      , module_path!()
                      , $msg, $status);
        println!("{:<38}{:>40}", concat!($dots, $msg), $status );
    };
    ( dots: $dots:expr, $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {}\n"
                      , module_path!()
                      , format_args!($($args)*));
        println!("{}{}", $dots, format_args!($($args)*)); }
    };
    ( $($args:tt)* ) => {
        { use core::fmt::Write;
        // TODO: only do this if we're in debug mode?
        // suppress warnings because we don't care if there's no serial port
        let _ = write!( $crate::arch::drivers::serial::COM1.lock()
                      , "[info] {}: {}\n"
                      , module_path!()
                      , format_args!($($args)*));
        println!( $($args)* ); }
    };
}
<|endoftext|>


<commit_before>#[derive(Debug)]
#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area,
            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64)
                as *const MemoryArea,
            entry_size: self.entry_size,
        }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct MemoryArea {
    base_addr: u64,
    length: u64,
    typ: u32,
    _reserved: u32,
}

impl MemoryArea {
    pub fn start_address(&self) -> usize {
        self.base_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.base_addr + self.length) as usize
    }

    pub fn size(&self) -> usize {
        self.length as usize
    }
}

#[derive(Clone, Debug)]
pub struct MemoryAreaIter {
    current_area: *const MemoryArea,
    last_area: *const MemoryArea,
    entry_size: u32,
}

impl Iterator for MemoryAreaIter {
    type Item = &'static MemoryArea;
    fn next(&mut self) -> Option<&'static MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*self.current_area};
            self.current_area = ((self.current_area as u64) + self.entry_size as u64)
                as *const MemoryArea;
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<commit_msg>Make MemoryMapIter be Send (#29)<commit_after>#[derive(Debug)]
#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area as u64,
            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64),
            entry_size: self.entry_size,
        }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct MemoryArea {
    base_addr: u64,
    length: u64,
    typ: u32,
    _reserved: u32,
}

impl MemoryArea {
    pub fn start_address(&self) -> usize {
        self.base_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.base_addr + self.length) as usize
    }

    pub fn size(&self) -> usize {
        self.length as usize
    }
}

#[derive(Clone, Debug)]
pub struct MemoryAreaIter {
    current_area: u64,
    last_area: u64,
    entry_size: u32,
}

impl Iterator for MemoryAreaIter {
    type Item = &'static MemoryArea;
    fn next(&mut self) -> Option<&'static MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*(self.current_area as *const MemoryArea)};
            self.current_area = self.current_area + (self.entry_size as u64);
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<|endoftext|>


<commit_before>//! Exposes the `Middleware` trait which must be implemented by
//! all middleware.

use std::fmt::Show;

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::chain::Chain;

/// The Status returned by `Middleware's` `enter` and `exit` methods. This indicates
/// to the `Chain` whether this is a terminal `Middleware` or whether to continue
/// passing the `Request` and `Response` down the `Chain's` stack.
///
/// Most `Chains` will ignore the returned `Status` from the `exit` method of
/// `Middleware`.
pub enum Status {
    /// `Continue` indicates that this is an intermediate `Middleware` in the stack
    /// and the `Chain` should continue passing requests down the `Chain's`
    /// stack.
    ///
    /// Most `Middleware` will return `Continue` from both `enter` and `exit`.
    Continue,

    /// `Unwind` indicates that this is a terminal `Middleware` or that something
    /// went wrong. It can be used to immediately stop passing requests down the
    /// `Chain's` stack and start calling `exit` of all previous `Middleware`.
    Unwind,
    ///
    /// For instance, an authorization `Middleware` might return `Unwind` if the
    /// `Request` fails an authentication check, and `Continue` otherwise.
    Error(Box<Show>)
}

/// All middleware should implement `Middleware`, which allows it to be `linked`
/// to a `Chain` so that it will be called for each incoming request.
///
/// There are two sorts of data associated with `Middleware`, data internal
/// to the `Middleware` and data that the `Middleware` would like to expose to
/// other `Middleware` further down the stack or to terminal controllers.
///
/// Internal data should be stored on the `struct` that implements `Middleware`
/// itself. All `Middleware` are cloned for each client request, so the object
/// initially linked to the `Iron` instance will be provided as `&mut self` to
/// enter for every request.
///
/// Data stored on a `Middleware` instance does _not_ persist
/// between requests and is _not_ shared between different, concurrent, requests.
/// The same is true for data stored on an `Alloy`.
///
/// Should you need to persist data between requests, you should use an `Arc`.
///
/// External data should be stored in the `Alloy` passed to both `enter` and
/// `exit`. `Alloy` is a thin wrapper around `AnyMap` and is effectively a
/// a key value store from a type to an instance of that type. This means
/// that each `Middleware` can have a unique type that it stores in the `Alloy`.
/// This can either be an instance of that `Middleware` or some other type. Since
/// the same `Alloy` is passed to all further `Middleware` in the `Chain`, this
/// scheme allows you to expose data or functionality to future `Middleware`.
pub trait Middleware: Send + Clone {
    /// `enter` is called for each `Middleware` in a `Chain` as a client request
    /// comes down the stack. `Middleware` have their `enter` methods called in the order
    /// in which they were added to the stack, that is, FIFO. `Middleware` should expose
    /// data through `Alloy` and store any data that will persist through the request here.
    ///
    /// Returning `Unwind` from this handler will cause the `Chain` to stop
    /// going down its stack and start bubbling back up through `Middleware`
    /// and calling `exit` on them.
    fn enter(&mut self,
             _: &mut Request,
             _: &mut Response,
             _: &mut Alloy) -> Status {
        Continue
    }

    /// `exit` is called for each `Middleware` in a `Chain` that has had its `enter`
    /// method called for this client request. A `Middleware's` `exit` method will be called
    /// as the stack is unwound in FILO order - i.e, `Middleware` have their `exit`
    /// methods called in opposite order from which `enter` was called.
    ///
    /// While this method must return a `Status`, most `Chains` will ignore
    /// this method's return value.
    fn exit(&mut self,
            _: &mut Request,
            _: &mut Response,
            _: &mut Alloy) -> Status {
        Continue
    }

    fn on_error(&mut self,
                _: &mut Request,
                _: &mut Response,
                _: &mut Alloy,
                _: &mut Show) { () }

    // Helper function to clone the Middleware.
    #[doc(hidden)]
    fn clone_box(&self) -> Box<Middleware + Send> { box self.clone() as Box<Middleware + Send> }
}

impl Clone for Box<Middleware + Send> {
    fn clone(&self) -> Box<Middleware + Send> { self.clone_box() }
}

impl Middleware for Box<Chain + Send> {
    fn enter(&mut self, request: &mut Request, response: &mut Response, alloy: &mut Alloy) -> Status {
        self.chain_enter(request, response, alloy)
    }

    fn exit(&mut self, request: &mut Request, response: &mut Response, alloy: &mut Alloy) -> Status {
        self.chain_exit(request, response, alloy)
    }

    fn on_error(&mut self, request: &mut Request, response: &mut Response,
                alloy: &mut Alloy, error: &mut Show) {
        self.chain_error(request, response, alloy, error)
    }
}

/// A temporary wrapper struct for allowing fn's to be used as Middleware
///
/// For instance, you can FromFn to wrap a simple controller:
///
/// ```
/// fn hello_world(...) -> Status { res.write(b"Hello World!"); Continue }
///
/// server.chain.link(FromFn::new(hello_world));
/// ```
///
pub struct FromFn {
    func: fn(&mut Request, &mut Response, &mut Alloy) -> Status
}

impl FromFn {
    /// Constructs a new FromFn given a fn of the correct signature.
    pub fn new(func: fn(&mut Request, &mut Response, &mut Alloy) -> Status) -> FromFn {
        FromFn {
            func: func
        }
    }
}

impl Clone for FromFn {
    fn clone(&self) -> FromFn {
        FromFn {
            func: self.func
        }
    }
}

impl Middleware for FromFn {
    fn enter(&mut self, res: &mut Request, req: &mut Response, alloy: &mut Alloy) -> Status {
        (self.func)(res, req, alloy)
    }
}

<commit_msg>(doc) Documented new Error variant.<commit_after>//! Exposes the `Middleware` trait which must be implemented by
//! all middleware.

use std::fmt::Show;

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::chain::Chain;

/// The Status returned by `Middleware's` `enter` and `exit` methods. This indicates
/// to the `Chain` whether this is a terminal `Middleware` or whether to continue
/// passing the `Request` and `Response` down the `Chain's` stack.
///
/// Most `Chains` will ignore the returned `Status` from the `exit` method of
/// `Middleware`.
pub enum Status {
    /// `Continue` indicates that this is an intermediate `Middleware` in the stack
    /// and the `Chain` should continue passing requests down the `Chain's`
    /// stack.
    ///
    /// Most `Middleware` will return `Continue` from both `enter` and `exit`.
    Continue,

    /// `Unwind` indicates that this is a terminal `Middleware`. It can be used to
    /// immediately stop passing requests down the `Chain's` stack and start calling
    /// `exit` of all previous `Middleware`.
    ///
    /// `Middleware` such as a router or controller, which are meant to handle
    /// requests completely should return `Unwind`.
    Unwind,

    /// `Error` indicates that something went wrong with a reason. It behaves
    /// similarly to `Unwind`, except that it instead calls `Middleware's`
    /// `on_error` handler as opposed to `exit`.
    ///
    /// For instance, an authorization `Middleware` might return `Error` if the
    /// `Request` fails an authentication check, and `Continue` otherwise.
    Error(Box<Show>)
}

/// All middleware should implement `Middleware`, which allows it to be `linked`
/// to a `Chain` so that it will be called for each incoming request.
///
/// There are two sorts of data associated with `Middleware`, data internal
/// to the `Middleware` and data that the `Middleware` would like to expose to
/// other `Middleware` further down the stack or to terminal controllers.
///
/// Internal data should be stored on the `struct` that implements `Middleware`
/// itself. All `Middleware` are cloned for each client request, so the object
/// initially linked to the `Iron` instance will be provided as `&mut self` to
/// enter for every request.
///
/// Data stored on a `Middleware` instance does _not_ persist
/// between requests and is _not_ shared between different, concurrent, requests.
/// The same is true for data stored on an `Alloy`.
///
/// Should you need to persist data between requests, you should use an `Arc`.
///
/// External data should be stored in the `Alloy` passed to both `enter` and
/// `exit`. `Alloy` is a thin wrapper around `AnyMap` and is effectively a
/// a key value store from a type to an instance of that type. This means
/// that each `Middleware` can have a unique type that it stores in the `Alloy`.
/// This can either be an instance of that `Middleware` or some other type. Since
/// the same `Alloy` is passed to all further `Middleware` in the `Chain`, this
/// scheme allows you to expose data or functionality to future `Middleware`.
pub trait Middleware: Send + Clone {
    /// `enter` is called for each `Middleware` in a `Chain` as a client request
    /// comes down the stack. `Middleware` have their `enter` methods called in the order
    /// in which they were added to the stack, that is, FIFO. `Middleware` should expose
    /// data through `Alloy` and store any data that will persist through the request here.
    ///
    /// Returning `Unwind` from this handler will cause the `Chain` to stop
    /// going down its stack and start bubbling back up through `Middleware`
    /// and calling `exit` on them.
    ///
    /// Returning `Error` from this handler will also cause "bubbling up" but
    /// will call `Middleware's`
    fn enter(&mut self,
             _: &mut Request,
             _: &mut Response,
             _: &mut Alloy) -> Status {
        Continue
    }

    /// `exit` is called for each `Middleware` in a `Chain` that has had its `enter`
    /// method called for this client request. A `Middleware's` `exit` method will be called
    /// as the stack is unwound in FILO order - i.e, `Middleware` have their `exit`
    /// methods called in opposite order from which `enter` was called.
    ///
    /// While this method must return a `Status`, most `Chains` will ignore
    /// this method's return value.
    fn exit(&mut self,
            _: &mut Request,
            _: &mut Response,
            _: &mut Alloy) -> Status {
        Continue
    }

    ///
    /// While this method must return a `Status`, most `Chains` will ignore
    /// this method's return value.
    fn on_error(&mut self,
                _: &mut Request,
                _: &mut Response,
                _: &mut Alloy,
                _: &mut Show) { () }

    // Helper function to clone the Middleware.
    #[doc(hidden)]
    fn clone_box(&self) -> Box<Middleware + Send> { box self.clone() as Box<Middleware + Send> }
}

impl Clone for Box<Middleware + Send> {
    fn clone(&self) -> Box<Middleware + Send> { self.clone_box() }
}

impl Middleware for Box<Chain + Send> {
    fn enter(&mut self, request: &mut Request, response: &mut Response, alloy: &mut Alloy) -> Status {
        self.chain_enter(request, response, alloy)
    }

    fn exit(&mut self, request: &mut Request, response: &mut Response, alloy: &mut Alloy) -> Status {
        self.chain_exit(request, response, alloy)
    }

    fn on_error(&mut self, request: &mut Request, response: &mut Response,
                alloy: &mut Alloy, error: &mut Show) {
        self.chain_error(request, response, alloy, error)
    }
}

/// A temporary wrapper struct for allowing fn's to be used as Middleware
///
/// For instance, you can FromFn to wrap a simple controller:
///
/// ```
/// fn hello_world(...) -> Status { res.write(b"Hello World!"); Continue }
///
/// server.chain.link(FromFn::new(hello_world));
/// ```
///
pub struct FromFn {
    func: fn(&mut Request, &mut Response, &mut Alloy) -> Status
}

impl FromFn {
    /// Constructs a new FromFn given a fn of the correct signature.
    pub fn new(func: fn(&mut Request, &mut Response, &mut Alloy) -> Status) -> FromFn {
        FromFn {
            func: func
        }
    }
}

impl Clone for FromFn {
    fn clone(&self) -> FromFn {
        FromFn {
            func: self.func
        }
    }
}

impl Middleware for FromFn {
    fn enter(&mut self, res: &mut Request, req: &mut Response, alloy: &mut Alloy) -> Status {
        (self.func)(res, req, alloy)
    }
}

<|endoftext|>


<commit_before>extern crate serde;

macro_rules! min_attribute_type {
    ($($name:ident,)*) => {
        $(
            #[derive(Debug, Serialize, Deserialize)]
            pub struct $name {
                href: String,
                name: String,
            }
        )*
    }
}

min_attribute_type! {
    Faction,
    Group,
    Rarity,
    CardLink,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Category {
    href: String,
    name: String,
    // WARNING: shouldn't be an Option but sometimes the field is missing
    uuid: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Variation {
    availability: String,
    href: String,
    rarity: Rarity,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Card {
    categories: Option<Vec<Category>>,
    faction: Faction,
    flavor: String,
    group: Group,
    href: String,
    info: String,
    name: String,
    positions: Vec<String>,
    strength: i64,
    uuid: String,
    variations: Vec<Variation>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PageCard {
    count: i64,
    next: Option<String>,
    previous: Option<String>,
    results: Vec<CardLink>,
}
<commit_msg>Minor name change.<commit_after>extern crate serde;

macro_rules! min_attribute_type {
    ($($name:ident,)*) => {
        $(
            #[derive(Debug, Serialize, Deserialize)]
            pub struct $name {
                href: String,
                name: String,
            }
        )*
    }
}

min_attribute_type! {
    Faction,
    Group,
    Rarity,
    CardLink,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Category {
    href: String,
    name: String,
    // WARNING: shouldn't be an Option but sometimes the field is missing
    uuid: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Variation {
    availability: String,
    href: String,
    rarity: Rarity,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Card {
    categories: Option<Vec<Category>>,
    faction: Faction,
    flavor: String,
    group: Group,
    href: String,
    info: String,
    name: String,
    positions: Vec<String>,
    strength: i64,
    uuid: String,
    variations: Vec<Variation>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CardPage {
    count: i64,
    next: Option<String>,
    previous: Option<String>,
    results: Vec<CardLink>,
}
<|endoftext|>


<commit_before>
use std::fmt;

use parser::ast_builder::FullToken;
use parser::tokenizer::Token;

#[derive(Debug, Clone, Copy)]
pub enum AstKind {
    Program,
    BlockStmt,
    VarStmt,
    EmptyStmt,
    IfStmt,
    ExprStmt,

    CondExpr,
    AssignExpr,
    CommaExpr,
    NameExpr
}
impl AstKind {
    fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

pub trait AstNode where Self: fmt::Debug {
    fn kind(&self) -> AstKind;
    fn is_statement(&self) -> bool;
    fn is_expression(&self) -> bool;
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error>;

    fn tree_string(&self) -> String {
        let mut str = String::new();
        self.write_tree(&mut str).unwrap();
        str
    }
}

/*****************************************************************************
 **** ProgramNode ************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct ProgramNode {
    source_elements: Vec<Box<AstNode>>
}
impl ProgramNode {
    pub fn new() -> ProgramNode {
        ProgramNode {
            source_elements: Vec::with_capacity(3)
        }
    }

    pub fn source_elements(&self) -> &Vec<Box<AstNode>> {
        &self.source_elements
    }
    pub fn add_source_element(&mut self, source_element: Box<AstNode>) {
        self.source_elements.push(source_element);
    }
}
impl AstNode for ProgramNode {
    fn kind(&self) -> AstKind {
        AstKind::Program
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("ProgramNode{")?;
        let mut first = true;
        for source_element in &self.source_elements {
            if ! first {
                w.write_str(", ")?;
            }
            first = false;
            source_element.write_tree(w)?;
        }
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** BlockStmtNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct BlockStmtNode {
}
impl BlockStmtNode {
    pub fn new() -> BlockStmtNode {
        BlockStmtNode {}
    }
}
impl AstNode for BlockStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::BlockStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Block{}")
    }
}

/*****************************************************************************
 **** VarStmtNode ************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct VarStmtNode {
    variables: Vec<Box<FullToken>>
}
impl VarStmtNode {
    pub fn new() -> VarStmtNode {
        VarStmtNode {
            variables: Vec::with_capacity(1)
        }
    }

    pub fn variables(&self) -> &Vec<Box<FullToken>> {
        &self.variables
    }
    pub fn add_variable(&mut self, var: FullToken) {
        self.variables.push(Box::new(var));
    }
}
impl AstNode for VarStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::VarStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Var{")?;
        let mut first = true;
        for variable in &self.variables {
            if ! first {
                w.write_str(", ")?;
            }
            first = false;
            variable.write_token(w)?;
        }
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** EmptyStmtNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct EmptyStmtNode {
}
impl EmptyStmtNode {
    pub fn new() -> EmptyStmtNode {
        EmptyStmtNode {}
    }
}
impl AstNode for EmptyStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::EmptyStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Empty{}")
    }
}

/*****************************************************************************
 **** IfStmtNode *************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct IfStmtNode {
    condition_expression: Box<AstNode>,
    if_statement: Box<AstNode>
}
impl IfStmtNode {
    pub fn new_if(condition_expression: Box<AstNode>, if_statement: Box<AstNode>)
        -> IfStmtNode
    {
        IfStmtNode {
            condition_expression: condition_expression,
            if_statement: if_statement
        }
    }

    pub fn condition_expression(&self) -> &AstNode {
        self.condition_expression.as_ref()
    }
    pub fn if_statement(&self) -> &AstNode {
        self.if_statement.as_ref()
    }
}
impl AstNode for IfStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::IfStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("If(")?;
        self.condition_expression.write_tree(w)?;
        w.write_str("){")?;
        self.if_statement.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** ExprStmtNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct ExprStmtNode {
    expression: Box<AstNode>
}
impl ExprStmtNode {
    pub fn new(expression: Box<AstNode>) -> ExprStmtNode {
        ExprStmtNode {
            expression: expression
        }
    }

    pub fn expression(&self) -> &AstNode {
        self.expression.as_ref()
    }
}
impl AstNode for ExprStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::ExprStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("ExprStmt{")?;
        self.expression.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** CondExprNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct CondExprNode {
    cond_expr: Box<AstNode>,
    if_expr: Box<AstNode>,
    else_expr: Box<AstNode>
}
impl CondExprNode {
    pub fn new(cond_expr: Box<AstNode>, if_expr: Box<AstNode>, else_expr: Box<AstNode>)
        -> CondExprNode
    {
        assert!(cond_expr.is_expression());
        assert!(if_expr.is_expression());
        assert!(else_expr.is_expression());
        CondExprNode {
            cond_expr: cond_expr,
            if_expr: if_expr,
            else_expr: else_expr
        }
    }

    pub fn cond_expr(&self) -> &AstNode {
        self.cond_expr.as_ref()
    }
    pub fn if_expr(&self) -> &AstNode {
        self.if_expr.as_ref()
    }
    pub fn else_expr(&self) -> &AstNode {
        self.else_expr.as_ref()
    }
}
impl AstNode for CondExprNode {
    fn kind(&self) -> AstKind {
        AstKind::CondExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("CondExpr{")?;
        self.cond_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.if_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.else_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** AssignExprNode *********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct AssignExprNode {
    assignment_op: FullToken,
    left_expr: Box<AstNode>,
    right_expr: Box<AstNode>
}
impl AssignExprNode {
    pub fn new(assignment_op: FullToken, left_expr: Box<AstNode>, right_expr: Box<AstNode>)
        -> AssignExprNode
    {
        // FIXME: assert that left_expr is a valid lvalue expression.
        assert!(left_expr.is_expression());
        assert!(right_expr.is_expression());
        assert!(assignment_op.kind().is_assignment_op());
        AssignExprNode {
            assignment_op: assignment_op,
            left_expr: left_expr,
            right_expr: right_expr
        }
    }

    pub fn assignment_op(&self) -> &FullToken {
        &self.assignment_op
    }
    pub fn left_expr(&self) -> &AstNode {
        self.left_expr.as_ref()
    }
    pub fn right_expr(&self) -> &AstNode {
        self.right_expr.as_ref()
    }
}
impl AstNode for AssignExprNode {
    fn kind(&self) -> AstKind {
        AstKind::AssignExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("AssignExpr(")?;
        self.assignment_op.write_token(w)?;
        w.write_str("){")?;
        self.left_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.right_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** CommaExprNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct CommaExprNode {
    left_expr: Box<AstNode>,
    right_expr: Box<AstNode>
}
impl CommaExprNode {
    pub fn new(left_expr: Box<AstNode>, right_expr: Box<AstNode>) -> CommaExprNode {
        assert!(left_expr.is_expression());
        assert!(right_expr.is_expression());
        CommaExprNode {
            left_expr: left_expr,
            right_expr: right_expr
        }
    }

    pub fn left_expr(&self) -> &AstNode {
        self.left_expr.as_ref()
    }
    pub fn right_expr(&self) -> &AstNode {
        self.right_expr.as_ref()
    }
}
impl AstNode for CommaExprNode {
    fn kind(&self) -> AstKind {
        AstKind::CommaExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("CommaExpr{")?;
        self.left_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.right_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** NameExprNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct NameExprNode {
    name: FullToken
}
impl NameExprNode {
    pub fn new(name: FullToken) -> NameExprNode {
        assert!(name.kind().is_identifier());
        NameExprNode {
            name: name
        }
    }

    pub fn name(&self) -> &FullToken {
        &self.name
    }
}
impl AstNode for NameExprNode {
    fn kind(&self) -> AstKind {
        AstKind::NameExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("NameExpr{")?;
        self.name.write_token(w);
        w.write_str("}")?;
        Ok(())
    }
}
<commit_msg>Shorted names and cleaned up syntax in AST structs.<commit_after>
use std::fmt;

use parser::ast_builder::FullToken;
use parser::tokenizer::Token;

#[derive(Debug, Clone, Copy)]
pub enum AstKind {
    Program,
    BlockStmt,
    VarStmt,
    EmptyStmt,
    IfStmt,
    ExprStmt,

    CondExpr,
    AssignExpr,
    CommaExpr,
    NameExpr
}
impl AstKind {
    fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

pub trait AstNode where Self: fmt::Debug {
    fn kind(&self) -> AstKind;
    fn is_statement(&self) -> bool;
    fn is_expression(&self) -> bool;
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error>;

    fn tree_string(&self) -> String {
        let mut str = String::new();
        self.write_tree(&mut str).unwrap();
        str
    }
}

/*****************************************************************************
 **** ProgramNode ************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct ProgramNode {
    source_elements: Vec<Box<AstNode>>
}
impl ProgramNode {
    pub fn new() -> ProgramNode {
        ProgramNode { source_elements: Vec::with_capacity(3) }
    }

    pub fn source_elements(&self) -> &Vec<Box<AstNode>> {
        &self.source_elements
    }
    pub fn add_source_element(&mut self, source_element: Box<AstNode>) {
        self.source_elements.push(source_element);
    }
}
impl AstNode for ProgramNode {
    fn kind(&self) -> AstKind {
        AstKind::Program
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("ProgramNode{")?;
        let mut first = true;
        for source_element in &self.source_elements {
            if ! first {
                w.write_str(", ")?;
            }
            first = false;
            source_element.write_tree(w)?;
        }
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** BlockStmtNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct BlockStmtNode {
}
impl BlockStmtNode {
    pub fn new() -> BlockStmtNode {
        BlockStmtNode {}
    }
}
impl AstNode for BlockStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::BlockStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Block{}")
    }
}

/*****************************************************************************
 **** VarStmtNode ************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct VarStmtNode {
    variables: Vec<Box<FullToken>>
}
impl VarStmtNode {
    pub fn new() -> VarStmtNode {
        VarStmtNode { variables: Vec::with_capacity(1) }
    }

    pub fn variables(&self) -> &Vec<Box<FullToken>> {
        &self.variables
    }
    pub fn add_variable(&mut self, var: FullToken) {
        self.variables.push(Box::new(var));
    }
}
impl AstNode for VarStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::VarStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Var{")?;
        let mut first = true;
        for variable in &self.variables {
            if ! first {
                w.write_str(", ")?;
            }
            first = false;
            variable.write_token(w)?;
        }
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** EmptyStmtNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct EmptyStmtNode {
}
impl EmptyStmtNode {
    pub fn new() -> EmptyStmtNode {
        EmptyStmtNode {}
    }
}
impl AstNode for EmptyStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::EmptyStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("Empty{}")
    }
}

/*****************************************************************************
 **** IfStmtNode *************************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct IfStmtNode {
    cond_expr: Box<AstNode>,
    if_true_stmt: Box<AstNode>
}
impl IfStmtNode {
    pub fn new_if(cond_expr: Box<AstNode>, if_true_stmt: Box<AstNode>)
        -> IfStmtNode
    {
        IfStmtNode { cond_expr, if_true_stmt }
    }

    pub fn cond_expr(&self) -> &AstNode {
        self.cond_expr.as_ref()
    }
    pub fn if_true_stmt(&self) -> &AstNode {
        self.if_true_stmt.as_ref()
    }
}
impl AstNode for IfStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::IfStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }

    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("If(")?;
        self.cond_expr.write_tree(w)?;
        w.write_str("){")?;
        self.if_true_stmt.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** ExprStmtNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct ExprStmtNode {
    expr: Box<AstNode>
}
impl ExprStmtNode {
    pub fn new(expr: Box<AstNode>) -> ExprStmtNode {
        assert!(expr.is_expression());
        ExprStmtNode { expr }
    }

    pub fn expression(&self) -> &AstNode {
        self.expr.as_ref()
    }
}
impl AstNode for ExprStmtNode {
    fn kind(&self) -> AstKind {
        AstKind::ExprStmt
    }
    fn is_statement(&self) -> bool {
        true
    }
    fn is_expression(&self) -> bool {
        false
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("ExprStmt{")?;
        self.expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** CondExprNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct CondExprNode {
    cond_expr: Box<AstNode>,
    if_expr: Box<AstNode>,
    else_expr: Box<AstNode>
}
impl CondExprNode {
    pub fn new(cond_expr: Box<AstNode>, if_expr: Box<AstNode>, else_expr: Box<AstNode>)
        -> CondExprNode
    {
        assert!(cond_expr.is_expression());
        assert!(if_expr.is_expression());
        assert!(else_expr.is_expression());
        CondExprNode { cond_expr, if_expr, else_expr }
    }

    pub fn cond_expr(&self) -> &AstNode {
        self.cond_expr.as_ref()
    }
    pub fn if_expr(&self) -> &AstNode {
        self.if_expr.as_ref()
    }
    pub fn else_expr(&self) -> &AstNode {
        self.else_expr.as_ref()
    }
}
impl AstNode for CondExprNode {
    fn kind(&self) -> AstKind {
        AstKind::CondExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("CondExpr{")?;
        self.cond_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.if_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.else_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** AssignExprNode *********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct AssignExprNode {
    assign_op: FullToken,
    left_expr: Box<AstNode>,
    right_expr: Box<AstNode>
}
impl AssignExprNode {
    pub fn new(assign_op: FullToken, left_expr: Box<AstNode>, right_expr: Box<AstNode>)
        -> AssignExprNode
    {
        // FIXME: assert that left_expr is a valid lvalue expression.
        assert!(left_expr.is_expression());
        assert!(right_expr.is_expression());
        assert!(assign_op.kind().is_assignment_op());
        AssignExprNode { assign_op, left_expr, right_expr }
    }

    pub fn assignment_op(&self) -> &FullToken {
        &self.assign_op
    }
    pub fn left_expr(&self) -> &AstNode {
        self.left_expr.as_ref()
    }
    pub fn right_expr(&self) -> &AstNode {
        self.right_expr.as_ref()
    }
}
impl AstNode for AssignExprNode {
    fn kind(&self) -> AstKind {
        AstKind::AssignExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("AssignExpr(")?;
        self.assign_op.write_token(w)?;
        w.write_str("){")?;
        self.left_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.right_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** CommaExprNode **********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct CommaExprNode {
    left_expr: Box<AstNode>,
    right_expr: Box<AstNode>
}
impl CommaExprNode {
    pub fn new(left_expr: Box<AstNode>, right_expr: Box<AstNode>) -> CommaExprNode {
        assert!(left_expr.is_expression());
        assert!(right_expr.is_expression());
        CommaExprNode { left_expr, right_expr }
    }

    pub fn left_expr(&self) -> &AstNode {
        self.left_expr.as_ref()
    }
    pub fn right_expr(&self) -> &AstNode {
        self.right_expr.as_ref()
    }
}
impl AstNode for CommaExprNode {
    fn kind(&self) -> AstKind {
        AstKind::CommaExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("CommaExpr{")?;
        self.left_expr.write_tree(w)?;
        w.write_str(", ")?;
        self.right_expr.write_tree(w)?;
        w.write_str("}")?;
        Ok(())
    }
}

/*****************************************************************************
 **** NameExprNode ***********************************************************
 *****************************************************************************/
#[derive(Debug)]
pub struct NameExprNode {
    name: FullToken
}
impl NameExprNode {
    pub fn new(name: FullToken) -> NameExprNode {
        assert!(name.kind().is_identifier());
        NameExprNode { name }
    }

    pub fn name(&self) -> &FullToken {
        &self.name
    }
}
impl AstNode for NameExprNode {
    fn kind(&self) -> AstKind {
        AstKind::NameExpr
    }
    fn is_statement(&self) -> bool {
        false
    }
    fn is_expression(&self) -> bool {
        true
    }
    fn write_tree(&self, w: &mut fmt::Write) -> Result<(), fmt::Error> {
        w.write_str("NameExpr{")?;
        self.name.write_token(w);
        w.write_str("}")?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use game_state;
use std;
use rand;
use rand::Rng;
use std::collections::HashSet;
use std::collections::HashMap;

#[derive(Debug, Copy, Clone)]
pub struct UCTData{
    pub wins : f64,
    pub num_plays : i32
}

impl UCTData{
    fn new(w : f64, n : i32) -> UCTData{
        UCTData{
            wins : w,
            num_plays : n
        }
    }

    fn win_percentage(&self) -> f64{
        (self.wins / self.num_plays as f64)
    }
}

pub struct TreePolicyResult{
    pub path : Vec<game_state::GameState>,
    pub expanded_node : game_state::GameState
}

impl TreePolicyResult{
    pub fn new(path : Vec<game_state::GameState>,
        expanded_node : game_state::GameState) -> TreePolicyResult{
            TreePolicyResult{
                path : path,
                expanded_node : expanded_node
            }
    }
}

fn test(){
    //println!("ass");
}

fn ucb1(win_value : f64, number_played : f64, total_played : f64) -> f64{
    ((f64::from(2) * total_played.ln()) / number_played).sqrt() + win_value / number_played
}

fn victory(end : game_state::End) -> bool{
    match end{
        game_state::End::Victory(_) => true,
        game_state::End::Tie => true,
        _ => false
    }
}

pub fn choose_random(rng : &mut rand::ThreadRng, possible_moves : &Vec<game_state::Move>) -> game_state::Move{
    let random_number = rng.gen::<usize>() % possible_moves.len();
    let random_move = possible_moves[random_number].clone();
    return random_move;
}

pub fn run_simulation(rng : &mut rand::ThreadRng ,state : game_state::GameState, player : game_state::Color) -> f64{

    let mut current_state = state;
    while (!victory(current_state.win())){
        let current_player = current_state.player;
        let possible_moves = state.legal_moves(current_player);
        if possible_moves.len() < 1{
            break;
        }
        let random_number = rng.gen::<usize>() % possible_moves.len();
        let random_move = possible_moves[random_number];
        current_state = current_state.place(&random_move);
    }

    match current_state.win(){
        game_state::End::Ongoing => 0f64,
        game_state::End::Tie => 0.3f64,
        game_state::End::Victory(color) => {
            if color == player{
                1f64
            }
            else{
                0f64
            }
        }
    }
}

pub fn tree_search(root : game_state::GameState){

    //keeps track of visisted states so we know if current state is a leaf
    let mut visited_states : HashSet<game_state::GameState> = std::collections::HashSet::new();
    visited_states.insert(root);
    let mut statistics : HashMap<game_state::GameState, UCTData> = HashMap::new();
    statistics.insert(root, UCTData::new(0f64, 0));

    let mut rng = rand::thread_rng();
    //get possible child states

    //temp
    for i in 0..5000{
        let current_state = root;

        //selection
        let selected_state = tree_policy(&current_state, &visited_states, &statistics);

        //expand
        statistics.insert(selected_state.expanded_node, UCTData::new(0f64, 0));
        visited_states.insert(selected_state.expanded_node);

        //simulate
        let result = run_simulation(&mut rng, selected_state.expanded_node, root.player);

        //backpropogate
        back_propogate(result, &mut statistics, &selected_state.path);
    }

    let possible_moves = root.legal_moves(root.player).into_iter().map(|x| (x, statistics.get(&root.place(&x)).unwrap())).collect::<Vec<_>>();
    let mut most_wins = 0;
    let best_move = game_state::Move::white_new(0, 0);
    for (mv, data) in possible_moves{

    }
    //let possible_states = possible_moves.into_iter().map(|x| root.place(&x)).map(|y| (y, statistics.get(&y).unwrap())).collect::<Vec<_>>();

}

pub fn tree_policy(
    current_state : &game_state::GameState,
    visisted_states : &HashSet<game_state::GameState>,
    stats : &HashMap<game_state::GameState, UCTData>
    ) -> TreePolicyResult{
    //selects a node to simulate
    let mut rng = rand::thread_rng();

    //represents the states we went through to get to the selected node
    let mut path : Vec<game_state::GameState> = Vec::new();

    let mut current_node = current_state.clone();
    loop{

        path.push(current_node);

        let mut possible_moves = current_node.legal_moves(current_node.player);

        if possible_moves.len() < 1{
            //no legal moves
            return TreePolicyResult::new(path, current_node);
        }
        //has every possible move been explored?
        let fully_explored = possible_moves.iter().fold(true,
            |acc, x|
            acc && visisted_states.contains(&current_node.place(x))
        );

        //exploration
        if !fully_explored {
            let not_explored = possible_moves.into_iter().filter(
                |x| !visisted_states.contains(&current_node.place(x))
                ).collect::<Vec<_>>();
            let random_choice = choose_random(&mut rng, &not_explored);
            let chosen_node = current_node.place(&random_choice);
            let result = TreePolicyResult::new(path, chosen_node);
            return result;
        }

        //fully explored, so pick a random one and continue
        //would use UCT
        else{
            //sort
            let mut best_move = possible_moves.last();
            let mut best_UCT = 0;
            for possibility in possible_moves.iter(){
            }
             let random_choice = choose_random(&mut rng, &possible_moves);
             let chosen_node = current_node.place(&random_choice);
             current_node = chosen_node;
        }
    }
}

pub fn back_propogate(win_value : f64, stats : &mut HashMap<game_state::GameState, UCTData>,
    path : &Vec<game_state::GameState>){
        for node in path.iter(){
            match stats.get_mut(node){
                Some(ref mut stat) =>{
                    stat.wins += win_value;
                    stat.num_plays += 1;
                }
                None => ()
            }
        }
}
<commit_msg>now selects with ucb1<commit_after>use game_state;
use std;
use rand;
use rand::Rng;
use std::collections::HashSet;
use std::collections::HashMap;

#[derive(Debug, Copy, Clone)]
pub struct UCTData{
    pub wins : f64,
    pub num_plays : i32
}

impl UCTData{
    fn new(w : f64, n : i32) -> UCTData{
        UCTData{
            wins : w,
            num_plays : n
        }
    }

    fn win_percentage(&self) -> f64{
        (self.wins / self.num_plays as f64)
    }
}

pub struct TreePolicyResult{
    pub path : Vec<game_state::GameState>,
    pub expanded_node : game_state::GameState
}

impl TreePolicyResult{
    pub fn new(path : Vec<game_state::GameState>,
        expanded_node : game_state::GameState) -> TreePolicyResult{
            TreePolicyResult{
                path : path,
                expanded_node : expanded_node
            }
    }
}

fn test(){
    //println!("ass");
}

fn ucb1(win_value : f64, number_played : f64, total_played : f64) -> f64{
    ((2f64 * total_played.ln()) / number_played).sqrt() + win_value / number_played
}

fn victory(end : game_state::End) -> bool{
    match end{
        game_state::End::Victory(_) => true,
        game_state::End::Tie => true,
        _ => false
    }
}

pub fn choose_random(rng : &mut rand::ThreadRng, possible_moves : &Vec<game_state::Move>) -> game_state::Move{
    let random_number = rng.gen::<usize>() % possible_moves.len();
    let random_move = possible_moves[random_number].clone();
    return random_move;
}

pub fn run_simulation(rng : &mut rand::ThreadRng ,state : game_state::GameState, player : game_state::Color) -> f64{

    let mut current_state = state;
    while (!victory(current_state.win())){
        let current_player = current_state.player;
        let possible_moves = state.legal_moves(current_player);
        if possible_moves.len() < 1{
            break;
        }
        let random_number = rng.gen::<usize>() % possible_moves.len();
        let random_move = possible_moves[random_number];
        current_state = current_state.place(&random_move);
    }

    match current_state.win(){
        game_state::End::Ongoing => 0f64,
        game_state::End::Tie => 0.3f64,
        game_state::End::Victory(color) => {
            if color == player{
                1f64
            }
            else{
                0f64
            }
        }
    }
}

pub fn tree_search(root : game_state::GameState){

    //keeps track of visisted states so we know if current state is a leaf
    let mut visited_states : HashSet<game_state::GameState> = std::collections::HashSet::new();
    visited_states.insert(root);
    let mut statistics : HashMap<game_state::GameState, UCTData> = HashMap::new();
    statistics.insert(root, UCTData::new(0f64, 0));

    let mut rng = rand::thread_rng();
    //get possible child states

    //temp
    for i in 0..5000{
        let current_state = root;

        //selection
        let selected_state = tree_policy(&current_state, &visited_states, &statistics);

        //expand
        statistics.insert(selected_state.expanded_node, UCTData::new(0f64, 0));
        visited_states.insert(selected_state.expanded_node);

        //simulate
        let result = run_simulation(&mut rng, selected_state.expanded_node, root.player);

        //backpropogate
        back_propogate(result, &mut statistics, &selected_state.path);
    }

    let possible_moves = root.legal_moves(root.player).into_iter().map(|x| (x, statistics.get(&root.place(&x)).unwrap())).collect::<Vec<_>>();
    let mut most_wins = 0;
    let best_move = game_state::Move::white_new(0, 0);
    for (mv, data) in possible_moves{

    }
    //let possible_states = possible_moves.into_iter().map(|x| root.place(&x)).map(|y| (y, statistics.get(&y).unwrap())).collect::<Vec<_>>();

}

pub fn tree_policy(
    current_state : &game_state::GameState,
    visisted_states : &HashSet<game_state::GameState>,
    stats : &HashMap<game_state::GameState, UCTData>
    ) -> TreePolicyResult{
    //selects a node to simulate
    let mut rng = rand::thread_rng();

    //represents the states we went through to get to the selected node
    let mut path : Vec<game_state::GameState> = Vec::new();

    let mut current_node = current_state.clone();
    loop{

        path.push(current_node);

        let mut possible_moves = current_node.legal_moves(current_node.player);

        if possible_moves.len() < 1{
            //no legal moves
            return TreePolicyResult::new(path, current_node);
        }
        //has every possible move been explored?
        let fully_explored = possible_moves.iter().fold(true,
            |acc, x|
            acc && visisted_states.contains(&current_node.place(x))
        );

        //exploration
        if !fully_explored {
            let not_explored = possible_moves.into_iter().filter(
                |x| !visisted_states.contains(&current_node.place(x))
                ).collect::<Vec<_>>();
            let random_choice = choose_random(&mut rng, &not_explored);
            let chosen_node = current_node.place(&random_choice);
            let result = TreePolicyResult::new(path, chosen_node);
            return result;
        }

        //fully explored, so pick a random one and continue
        //would use UCT
        else{
            //sort
            let mut best_move = possible_moves.last().unwrap();
            let mut best_UCT = 0f64;
            let total_played = stats.get(&current_state).unwrap().num_plays;
            for possibility in possible_moves.iter(){

                //TODO: switch to pattern matching
                let data = stats.get(&current_node.place(&possibility)).unwrap();
                let uct = ucb1(data.wins, data.num_plays as f64, total_played as f64);
                if(uct > best_UCT){
                    best_UCT = uct;
                    best_move = possibility;
                }
            }
            let chosen_node = current_node.place(&best_move);
            current_node = chosen_node;
        }
    }
}

pub fn back_propogate(win_value : f64, stats : &mut HashMap<game_state::GameState, UCTData>,
    path : &Vec<game_state::GameState>){
        for node in path.iter(){
            match stats.get_mut(node){
                Some(ref mut stat) =>{
                    stat.wins += win_value;
                    stat.num_plays += 1;
                }
                None => ()
            }
        }
}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        // libssh2 is linked in elsehwere, don't want it reported via pkg-config
        let pc = dst.join("lib/pkgconfig/libgit2.pc");
        let mut contents = String::new();
        t!(t!(File::open(&pc)).read_to_string(&mut contents));
        let contents = contents.replace(" -lssh2 ", " ");
        t!(t!(File::create(&pc)).write_all(contents.as_bytes()));

        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<commit_msg>Don't use pkg-config to learn about libgit2 deps<commit_after>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<|endoftext|>


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

#[cfg(feature = "amqp-build-specs")]
include!(concat!(env!("OUT_DIR"), "/amqp0.rs"));
#[cfg(not(feature = "amqp-build-specs"))]
include!(concat!("mod.pregen.rs"));

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Version {
    minor: u16,
    revision: u16,
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Spec {
    name: &'static str,
    classes: BTreeMap<&'static str, Class>,
    constants: BTreeMap<&'static str, Constant>,
    domains: BTreeMap<&'static str, &'static str>,
    frame_types: BTreeMap<&'static str, Constant>,
    response_codes: BTreeMap<&'static str, Constant>,
    version: Version,
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Class {
    name: &'static str,
    index: u16,
    methods: Vec<ClassMethod>,
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct ClassMethod {
    name: &'static str,
    index: u16,
    response: Option<&'static str>,
    fields: Vec<ClassMethodField>,
    is_synchronous: bool,

    chassis_server: Option<&'static str>,
    chassis_client: Option<&'static str>,
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct ClassMethodField {
    name: &'static str,
    domain: &'static str,
    assertions: Vec<ClassMethodFieldAssertion>,
    is_reserved: bool,
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub enum ClassMethodFieldAssertion {
    Null,
    NotNull,
    ChannelMax,
    NotZero,
    Enum(Vec<&'static str>),
    Length(usize),
    Regexp(&'static str),
    Syntax(&'static str),
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Constant {
    name: &'static str,
    value: u32,
    class: Option<&'static str>,
}

impl Spec {
    pub fn name(&self) -> &'static str {
        self.name
    }
    pub fn classes(&self) -> &BTreeMap<&'static str, Class> {
        &self.classes
    }
    pub fn domains(&self) -> &BTreeMap<&'static str, &'static str> {
        &self.domains
    }
    pub fn frame_types(&self) -> &BTreeMap<&'static str, Constant> {
        &self.frame_types
    }
    pub fn response_codes(&self) -> &BTreeMap<&'static str, Constant> {
        &self.response_codes
    }
    pub fn version(&self) -> &Version {
        &self.version
    }
}

impl Class {
    pub fn name(&self) -> &'static str {
        self.name
    }

    pub fn index(&self) -> u16 {
        self.index
    }

    pub fn methods(&self) -> &Vec<ClassMethod> {
        &self.methods
    }
}

impl ClassMethod {
    pub fn index(&self) -> u16 {
        self.index
    }
    pub fn name(&self) -> &str {
        &self.name
    }
    pub fn fields(&self) -> &Vec<ClassMethodField> {
        &self.fields
    }
}

impl ClassMethodField {
    pub fn name(&self) -> &'static str {
        &self.name
    }

    pub fn domain(&self) -> &'static str {
        self.domain
    }

    pub fn assertions(&self) -> &Vec<ClassMethodFieldAssertion> {
        &self.assertions
    }

    pub fn is_reserved(&self) -> bool {
        self.is_reserved
    }
}

impl Constant {
    pub fn name(&self) -> &'static str {
        self.name
    }

    pub fn value(&self) -> u32 {
        self.value
    }

    pub fn class(&self) -> Option<&'static str> {
        self.class
    }
}

impl Version {
    pub fn minor(&self) -> u16 {
        self.minor
    }

    pub fn revision(&self) -> u16 {
        self.revision
    }
}<commit_msg>[specs] Implement Clone on top-level structs<commit_after>
use std::collections::BTreeMap;

#[cfg(feature = "amqp-build-specs")]
include!(concat!(env!("OUT_DIR"), "/amqp0.rs"));
#[cfg(not(feature = "amqp-build-specs"))]
include!(concat!("mod.pregen.rs"));

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Version {
    minor: u16,
    revision: u16,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Spec {
    name: &'static str,
    classes: BTreeMap<&'static str, Class>,
    constants: BTreeMap<&'static str, Constant>,
    domains: BTreeMap<&'static str, &'static str>,
    frame_types: BTreeMap<&'static str, Constant>,
    response_codes: BTreeMap<&'static str, Constant>,
    version: Version,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Class {
    name: &'static str,
    index: u16,
    methods: Vec<ClassMethod>,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct ClassMethod {
    name: &'static str,
    index: u16,
    response: Option<&'static str>,
    fields: Vec<ClassMethodField>,
    is_synchronous: bool,

    chassis_server: Option<&'static str>,
    chassis_client: Option<&'static str>,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct ClassMethodField {
    name: &'static str,
    domain: &'static str,
    assertions: Vec<ClassMethodFieldAssertion>,
    is_reserved: bool,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum ClassMethodFieldAssertion {
    Null,
    NotNull,
    ChannelMax,
    NotZero,
    Enum(Vec<&'static str>),
    Length(usize),
    Regexp(&'static str),
    Syntax(&'static str),
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Constant {
    name: &'static str,
    value: u32,
    class: Option<&'static str>,
}

impl Spec {
    pub fn name(&self) -> &'static str {
        self.name
    }
    pub fn classes(&self) -> &BTreeMap<&'static str, Class> {
        &self.classes
    }
    pub fn domains(&self) -> &BTreeMap<&'static str, &'static str> {
        &self.domains
    }
    pub fn frame_types(&self) -> &BTreeMap<&'static str, Constant> {
        &self.frame_types
    }
    pub fn response_codes(&self) -> &BTreeMap<&'static str, Constant> {
        &self.response_codes
    }
    pub fn version(&self) -> &Version {
        &self.version
    }
}

impl Class {
    pub fn name(&self) -> &'static str {
        self.name
    }

    pub fn index(&self) -> u16 {
        self.index
    }

    pub fn methods(&self) -> &Vec<ClassMethod> {
        &self.methods
    }
}

impl ClassMethod {
    pub fn index(&self) -> u16 {
        self.index
    }
    pub fn name(&self) -> &str {
        &self.name
    }
    pub fn fields(&self) -> &Vec<ClassMethodField> {
        &self.fields
    }
}

impl ClassMethodField {
    pub fn name(&self) -> &'static str {
        &self.name
    }

    pub fn domain(&self) -> &'static str {
        self.domain
    }

    pub fn assertions(&self) -> &Vec<ClassMethodFieldAssertion> {
        &self.assertions
    }

    pub fn is_reserved(&self) -> bool {
        self.is_reserved
    }
}

impl Constant {
    pub fn name(&self) -> &'static str {
        self.name
    }

    pub fn value(&self) -> u32 {
        self.value
    }

    pub fn class(&self) -> Option<&'static str> {
        self.class
    }
}

impl Version {
    pub fn minor(&self) -> u16 {
        self.minor
    }

    pub fn revision(&self) -> u16 {
        self.revision
    }
}<|endoftext|>