<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Jordi Boggiano <j.boggiano@seld.be>
//  * (c) Jian Zeng <anonymousknight86@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) getloadavg upsecs updays nusers loadavg boottime uphours upmins

use chrono::{Local, TimeZone, Utc};
use clap::{crate_version, App, Arg};

#[macro_use]
extern crate uucore;
// import crate time from utmpx
pub use uucore::libc;
use uucore::libc::time_t;

static ABOUT: &str = "Display the current time, the length of time the system has been up,\n\
                      the number of users on the system, and the average number of jobs\n\
                      in the run queue over the last 1, 5 and 15 minutes.";
pub mod options {
    pub static SINCE: &str = "since";
}

#[cfg(unix)]
use uucore::libc::getloadavg;

#[cfg(windows)]
extern "C" {
    fn GetTickCount() -> uucore::libc::uint32_t;
}

fn usage() -> String {
    format!("{0} [OPTION]...", uucore::execution_phrase())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = usage();
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let (boot_time, user_count) = process_utmpx();
    let uptime = get_uptime(boot_time);
    if uptime < 0 {
        show_error!("could not retrieve system uptime");

        1
    } else {
        if matches.is_present(options::SINCE) {
            let initial_date = Local.timestamp(Utc::now().timestamp() - uptime, 0);
            println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
            return 0;
        }

        print_time();
        let upsecs = uptime;
        print_uptime(upsecs);
        print_nusers(user_count);
        print_loadavg();

        0
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .arg(
            Arg::with_name(options::SINCE)
                .short("s")
                .long(options::SINCE)
                .help("system up since"),
        )
}

#[cfg(unix)]
fn print_loadavg() {
    use uucore::libc::c_double;

    let mut avg: [c_double; 3] = [0.0; 3];
    let loads: i32 = unsafe { getloadavg(avg.as_mut_ptr(), 3) };

    if loads == -1 {
        println!();
    } else {
        print!("load average: ");
        for n in 0..loads {
            print!(
                "{:.2}{}",
                avg[n as usize],
                if n == loads - 1 { "\n" } else { ", " }
            );
        }
    }
}

#[cfg(windows)]
fn print_loadavg() {
    // XXX: currently this is a noop as Windows does not seem to have anything comparable to
    //      getloadavg()
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, usize) {
    use uucore::utmpx::*;

    let mut nusers = 0;
    let mut boot_time = None;

    for line in Utmpx::iter_all_records() {
        match line.record_type() {
            USER_PROCESS => nusers += 1,
            BOOT_TIME => {
                let t = line.login_time().to_timespec();
                if t.sec > 0 {
                    boot_time = Some(t.sec as time_t);
                }
            }
            _ => continue,
        }
    }
    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, usize) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: usize) {
    match nusers.cmp(&1) {
        std::cmp::Ordering::Equal => print!("1 user,  "),
        std::cmp::Ordering::Greater => print!("{} users,  ", nusers),
        _ => {}
    };
}

fn print_time() {
    let local_time = Local::now().time();

    print!(" {} ", local_time.format("%H:%M:%S"));
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    use std::fs::File;
    use std::io::Read;

    let mut proc_uptime_s = String::new();

    let proc_uptime = File::open("/proc/uptime")
        .ok()
        .and_then(|mut f| f.read_to_string(&mut proc_uptime_s).ok())
        .and_then(|_| proc_uptime_s.split_whitespace().next())
        .and_then(|s| s.split('.').next().unwrap_or("0").parse().ok());

    proc_uptime.unwrap_or_else(|| match boot_time {
        Some(t) => {
            let now = Local::now().timestamp();
            let boottime = t as i64;
            now - boottime
        }
        None => -1,
    })
}

#[cfg(windows)]
fn get_uptime(_boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    match updays.cmp(&1) {
        std::cmp::Ordering::Equal => print!("up {:1} day, {:2}:{:02},  ", updays, uphours, upmins),
        std::cmp::Ordering::Greater => {
            print!("up {:1} days, {:2}:{:02},  ", updays, uphours, upmins)
        }
        _ => print!("up  {:2}:{:02}, ", uphours, upmins),
    };
}
<commit_msg>uptime: added UResult<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Jordi Boggiano <j.boggiano@seld.be>
//  * (c) Jian Zeng <anonymousknight86@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) getloadavg upsecs updays nusers loadavg boottime uphours upmins

use chrono::{Local, TimeZone, Utc};
use clap::{crate_version, App, Arg};

#[macro_use]
extern crate uucore;
// import crate time from utmpx
pub use uucore::libc;
use uucore::libc::time_t;

use uucore::error::{UResult, USimpleError};

static ABOUT: &str = "Display the current time, the length of time the system has been up,\n\
                      the number of users on the system, and the average number of jobs\n\
                      in the run queue over the last 1, 5 and 15 minutes.";
pub mod options {
    pub static SINCE: &str = "since";
}

#[cfg(unix)]
use uucore::libc::getloadavg;

#[cfg(windows)]
extern "C" {
    fn GetTickCount() -> uucore::libc::uint32_t;
}

fn usage() -> String {
    format!("{0} [OPTION]...", uucore::execution_phrase())
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let usage = usage();
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let (boot_time, user_count) = process_utmpx();
    let uptime = get_uptime(boot_time);
    if uptime < 0 {
        Err(USimpleError::new(1, "could not retrieve system uptime"))
    } else {
        if matches.is_present(options::SINCE) {
            let initial_date = Local.timestamp(Utc::now().timestamp() - uptime, 0);
            println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
            return Ok(());
        }

        print_time();
        let upsecs = uptime;
        print_uptime(upsecs);
        print_nusers(user_count);
        print_loadavg();

        Ok(())
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .arg(
            Arg::with_name(options::SINCE)
                .short("s")
                .long(options::SINCE)
                .help("system up since"),
        )
}

#[cfg(unix)]
fn print_loadavg() {
    use uucore::libc::c_double;

    let mut avg: [c_double; 3] = [0.0; 3];
    let loads: i32 = unsafe { getloadavg(avg.as_mut_ptr(), 3) };

    if loads == -1 {
        println!();
    } else {
        print!("load average: ");
        for n in 0..loads {
            print!(
                "{:.2}{}",
                avg[n as usize],
                if n == loads - 1 { "\n" } else { ", " }
            );
        }
    }
}

#[cfg(windows)]
fn print_loadavg() {
    // XXX: currently this is a noop as Windows does not seem to have anything comparable to
    //      getloadavg()
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, usize) {
    use uucore::utmpx::*;

    let mut nusers = 0;
    let mut boot_time = None;

    for line in Utmpx::iter_all_records() {
        match line.record_type() {
            USER_PROCESS => nusers += 1,
            BOOT_TIME => {
                let t = line.login_time().to_timespec();
                if t.sec > 0 {
                    boot_time = Some(t.sec as time_t);
                }
            }
            _ => continue,
        }
    }
    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, usize) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: usize) {
    match nusers.cmp(&1) {
        std::cmp::Ordering::Equal => print!("1 user,  "),
        std::cmp::Ordering::Greater => print!("{} users,  ", nusers),
        _ => {}
    };
}

fn print_time() {
    let local_time = Local::now().time();

    print!(" {} ", local_time.format("%H:%M:%S"));
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    use std::fs::File;
    use std::io::Read;

    let mut proc_uptime_s = String::new();

    let proc_uptime = File::open("/proc/uptime")
        .ok()
        .and_then(|mut f| f.read_to_string(&mut proc_uptime_s).ok())
        .and_then(|_| proc_uptime_s.split_whitespace().next())
        .and_then(|s| s.split('.').next().unwrap_or("0").parse().ok());

    proc_uptime.unwrap_or_else(|| match boot_time {
        Some(t) => {
            let now = Local::now().timestamp();
            let boottime = t as i64;
            now - boottime
        }
        None => -1,
    })
}

#[cfg(windows)]
fn get_uptime(_boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    match updays.cmp(&1) {
        std::cmp::Ordering::Equal => print!("up {:1} day, {:2}:{:02},  ", updays, uphours, upmins),
        std::cmp::Ordering::Greater => {
            print!("up {:1} days, {:2}:{:02},  ", updays, uphours, upmins)
        }
        _ => print!("up  {:2}:{:02}, ", uphours, upmins),
    };
}
<|endoftext|>


<commit_before>#[derive(StructOpt, PartialEq, Debug)]
pub struct App {
  #[structopt(short="c", long = "config", help = "Sets a custom config file")]
  pub config: String,
  #[structopt(subcommand)]
  pub cmd: SubCmd,
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum SubCmd {
  #[structopt(name = "shutdown", about = "shuts down the proxy without waiting for connections to finish")]
  Shutdown {
    #[structopt(short = "h", long = "hard", default_value="false")]
    hard: bool
  },
  #[structopt(name = "upgrade", about = "upgrade the proxy")]
  Upgrade,
  #[structopt(name = "status", about = "gets information on the running workers")]
  Status,
  #[structopt(name = "metrics", about = "gets statistics on the master and its workers")]
  Metrics,
  #[structopt(name = "logging", about = "change logging level")]
  Logging {
    #[structopt(short = "l", long = "level", help = "change logging level")]
    level: String
  },
  #[structopt(name = "state", about = "state management")]
  State {
    #[structopt(subcommand)]
    cmd: StateCmd,
  },
  #[structopt(name = "application", about = "application management")]
  Application {
    #[structopt(subcommand)]
    cmd: ApplicationCmd,
  },
  #[structopt(name = "backend", about = "backend management")]
  Backend {
    #[structopt(subcommand)]
    cmd: BackendCmd,
  },
  #[structopt(name = "frontend", about = "frontend management")]
  Frontend {
    #[structopt(subcommand)]
    cmd: FrontendCmd,
  },
  #[structopt(name = "certificate", about = "certificate management")]
  Certificate {
    #[structopt(subcommand)]
    cmd: CertificateCmd,
  },
  #[structopt(name = "query", about = "configuration state verification")]
  Query {
    #[structopt(subcommand)]
    cmd: QueryCmd,
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum StateCmd {
  #[structopt(name = "save", about = "Save state to that file")]
  Save {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "load", about = "Load state from that file")]
  Load {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "dump")]
  Dump,
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum ApplicationCmd {
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
  },
  #[structopt(name = "add")]
  Add{
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(short = "s", long = "sticky-session", default_value="false")]
    sticky_session: bool,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum BackendCmd {
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "instance-id")]
    instance_id: String,
    #[structopt(long = "ip")]
    ip: String,
    #[structopt(short = "p", long = "port")]
    port: u16,
  },
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "instance-id")]
    instance_id: String,
    #[structopt(long = "ip")]
    ip: String,
    #[structopt(short = "p", long = "port")]
    port: u16,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum FrontendCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
    #[structopt(long = "certificate", help="path to a certificate file")]
    path_to_certificate: Option<String>,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
    #[structopt(long = "certificate", help="path to a certificate file")]
    path_to_certificate: Option<String>,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum CertificateCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(long = "certificate", help = "path to the certificate")]
    certificate: String,
    #[structopt(long = "certificate-chain", help = "path to the certificate chain")]
    chain: String,
    #[structopt(long = "key", help = "path to the key")]
    key: Option<String>,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "cert", long = "certificate", help = "path to the certificate")]
    certificate: String,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum QueryCmd {
  #[structopt(name = "applications")]
  Applications {
    #[structopt(short = "i", long="id", help="application identifier")]
    id: Option<String>
  }
}<commit_msg>Remove default_value on Option<bool> to avoid to call the command with cmd --flag true AND fix shutdown and Application flags errors<commit_after>#[derive(StructOpt, PartialEq, Debug)]
pub struct App {
  #[structopt(short="c", long = "config", help = "Sets a custom config file")]
  pub config: String,
  #[structopt(subcommand)]
  pub cmd: SubCmd,
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum SubCmd {
  #[structopt(name = "shutdown", about = "shuts down the proxy without waiting for connections to finish")]
  Shutdown {
    #[structopt(short = "h", long = "hard")]
    hard: bool
  },
  #[structopt(name = "upgrade", about = "upgrade the proxy")]
  Upgrade,
  #[structopt(name = "status", about = "gets information on the running workers")]
  Status,
  #[structopt(name = "metrics", about = "gets statistics on the master and its workers")]
  Metrics,
  #[structopt(name = "logging", about = "change logging level")]
  Logging {
    #[structopt(short = "l", long = "level", help = "change logging level")]
    level: String
  },
  #[structopt(name = "state", about = "state management")]
  State {
    #[structopt(subcommand)]
    cmd: StateCmd,
  },
  #[structopt(name = "application", about = "application management")]
  Application {
    #[structopt(subcommand)]
    cmd: ApplicationCmd,
  },
  #[structopt(name = "backend", about = "backend management")]
  Backend {
    #[structopt(subcommand)]
    cmd: BackendCmd,
  },
  #[structopt(name = "frontend", about = "frontend management")]
  Frontend {
    #[structopt(subcommand)]
    cmd: FrontendCmd,
  },
  #[structopt(name = "certificate", about = "certificate management")]
  Certificate {
    #[structopt(subcommand)]
    cmd: CertificateCmd,
  },
  #[structopt(name = "query", about = "configuration state verification")]
  Query {
    #[structopt(subcommand)]
    cmd: QueryCmd,
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum StateCmd {
  #[structopt(name = "save", about = "Save state to that file")]
  Save {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "load", about = "Load state from that file")]
  Load {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "dump")]
  Dump,
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum ApplicationCmd {
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
  },
  #[structopt(name = "add")]
  Add{
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(short = "s", long = "sticky-session")]
    sticky_session: bool,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum BackendCmd {
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "instance-id")]
    instance_id: String,
    #[structopt(long = "ip")]
    ip: String,
    #[structopt(short = "p", long = "port")]
    port: u16,
  },
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "instance-id")]
    instance_id: String,
    #[structopt(long = "ip")]
    ip: String,
    #[structopt(short = "p", long = "port")]
    port: u16,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum FrontendCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
    #[structopt(long = "certificate", help="path to a certificate file")]
    path_to_certificate: Option<String>,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
    #[structopt(long = "certificate", help="path to a certificate file")]
    path_to_certificate: Option<String>,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum CertificateCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(long = "certificate", help = "path to the certificate")]
    certificate: String,
    #[structopt(long = "certificate-chain", help = "path to the certificate chain")]
    chain: String,
    #[structopt(long = "key", help = "path to the key")]
    key: Option<String>,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "cert", long = "certificate", help = "path to the certificate")]
    certificate: String,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum QueryCmd {
  #[structopt(name = "applications")]
  Applications {
    #[structopt(short = "i", long="id", help="application identifier")]
    id: Option<String>
  }
}<|endoftext|>


<commit_before>/**
Registers a selector, returning an `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:ident) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!(stringify!($name), '\0'))
    });
    ($($name:ident :)+) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!($(stringify!($name), ':'),+, '\0'))
    });
}

/**
Sends a message to an object.

The first argument should implement the `ToMessage` trait, and the syntax is
similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($name);
        $crate::MessageArguments::send_super((), to_mut(&*$obj), $superclass, sel)
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($($name:)+);
        $crate::MessageArguments::send_super(($($arg,)*), to_mut(&*$obj), $superclass, sel)
    });
    ($obj:expr, $name:ident) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($name);
        $crate::MessageArguments::send((), to_mut(&*$obj), sel)
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($($name:)+);
        $crate::MessageArguments::send(($($arg,)*), to_mut(&*$obj), sel)
    });
}

macro_rules! encode {
    () => ("");
    (i8 $($x:tt)*) => (concat!("c", encode!($($x)*)));
    (i16 $($x:tt)*) => (concat!("s", encode!($($x)*)));
    (i32 $($x:tt)*) => (concat!("i", encode!($($x)*)));
    (i64 $($x:tt)*) => (concat!("q", encode!($($x)*)));
    (u8 $($x:tt)*) => (concat!("C", encode!($($x)*)));
    (u16 $($x:tt)*) => (concat!("S", encode!($($x)*)));
    (u32 $($x:tt)*) => (concat!("I", encode!($($x)*)));
    (u64 $($x:tt)*) => (concat!("Q", encode!($($x)*)));
    (f32 $($x:tt)*) => (concat!("f", encode!($($x)*)));
    (f64 $($x:tt)*) => (concat!("d", encode!($($x)*)));
    (bool $($x:tt)*) => (concat!("B", encode!($($x)*)));
    (Sel $($x:tt)*) => (concat!(":", encode!($($x)*)));
    (struct $i:ident {$($x:tt)+}) => (
        concat!('{', stringify!($i), '=', encode!($($x)*), '}')
    );
    // Just eat a leading comma and continue
    (, $($x:tt)*) => (encode!($($x)*));
}
<commit_msg>Updated some macros docs.<commit_after>/**
Registers a selector, returning a `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:ident) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!(stringify!($name), '\0'))
    });
    ($($name:ident :)+) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!($(stringify!($name), ':'),+, '\0'))
    });
}

/**
Sends a message to an object.

The first argument can be any type that dereferences to a type that implements
`Message`, like a reference, pointer, or an `Id`.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($name);
        $crate::MessageArguments::send_super((), to_mut(&*$obj), $superclass, sel)
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($($name:)+);
        $crate::MessageArguments::send_super(($($arg,)*), to_mut(&*$obj), $superclass, sel)
    });
    ($obj:expr, $name:ident) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($name);
        $crate::MessageArguments::send((), to_mut(&*$obj), sel)
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        #[inline(always)]
        unsafe fn to_mut<T>(ptr: &T) -> *mut T { ptr as *const T as *mut T }
        let sel = sel!($($name:)+);
        $crate::MessageArguments::send(($($arg,)*), to_mut(&*$obj), sel)
    });
}

macro_rules! encode {
    () => ("");
    (i8 $($x:tt)*) => (concat!("c", encode!($($x)*)));
    (i16 $($x:tt)*) => (concat!("s", encode!($($x)*)));
    (i32 $($x:tt)*) => (concat!("i", encode!($($x)*)));
    (i64 $($x:tt)*) => (concat!("q", encode!($($x)*)));
    (u8 $($x:tt)*) => (concat!("C", encode!($($x)*)));
    (u16 $($x:tt)*) => (concat!("S", encode!($($x)*)));
    (u32 $($x:tt)*) => (concat!("I", encode!($($x)*)));
    (u64 $($x:tt)*) => (concat!("Q", encode!($($x)*)));
    (f32 $($x:tt)*) => (concat!("f", encode!($($x)*)));
    (f64 $($x:tt)*) => (concat!("d", encode!($($x)*)));
    (bool $($x:tt)*) => (concat!("B", encode!($($x)*)));
    (Sel $($x:tt)*) => (concat!(":", encode!($($x)*)));
    (struct $i:ident {$($x:tt)+}) => (
        concat!('{', stringify!($i), '=', encode!($($x)*), '}')
    );
    // Just eat a leading comma and continue
    (, $($x:tt)*) => (encode!($($x)*));
}
<|endoftext|>


<commit_before>use crate::mem::{size_of, transmute_copy};
use crate::ptr::write_bytes;

pub(super) trait SpecFill<T> {
    fn spec_fill(&mut self, value: T);
}

impl<T: Clone> SpecFill<T> for [T] {
    default fn spec_fill(&mut self, value: T) {
        if let Some((last, elems)) = self.split_last_mut() {
            for el in elems {
                el.clone_from(&value);
            }

            *last = value
        }
    }
}

impl<T: Copy> SpecFill<T> for [T] {
    fn spec_fill(&mut self, value: T) {
        if size_of::<T>() == 1 {
            // SAFETY: The size_of check above ensures that values are 1 byte wide, as required
            // for the transmute and write_bytes
            unsafe {
                let value: u8 = transmute_copy(&value);
                write_bytes(self.as_mut_ptr(), value, self.len());
            }
        } else {
            for item in self.iter_mut() {
                *item = value;
            }
        }
    }
}
<commit_msg>Remove size_of == 1 case from `fill` specialization.<commit_after>pub(super) trait SpecFill<T> {
    fn spec_fill(&mut self, value: T);
}

impl<T: Clone> SpecFill<T> for [T] {
    default fn spec_fill(&mut self, value: T) {
        if let Some((last, elems)) = self.split_last_mut() {
            for el in elems {
                el.clone_from(&value);
            }

            *last = value
        }
    }
}

impl<T: Copy> SpecFill<T> for [T] {
    fn spec_fill(&mut self, value: T) {
        for item in self.iter_mut() {
            *item = value;
        }
    }
}
<|endoftext|>


<commit_before>use super::{safe, try_into_option, Environment, DiagnosticRecord, GetDiagRec, Result, Version3};
use ffi;
use std::collections::HashMap;
use std::str::from_utf8;
use std::cmp::max;

/// Holds name and description of a datasource
///
/// Can be obtained via `Environment::data_sources`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataSourceInfo {
    /// Name of the data source
    pub server_name: String,
    /// Description of the data source
    pub driver: String,
}

/// Struct holding information available on a driver.
///
/// Can be obtained via `Environment::drivers`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DriverInfo {
    /// Name of the odbc driver
    pub description: String,
    /// List of attributes of the odbc driver
    pub attributes: HashMap<String, String>,
}

type SqlInfoMethod = fn(&mut safe::Environment<safe::Odbc3>,
                        ffi::FetchOrientation,
                        &mut [u8],
                        &mut [u8])
                        -> safe::ReturnOption<(i16, i16)>;

impl Environment<Version3> {
    /// Called by drivers to pares list of attributes
    ///
    /// Key value pairs are seperated by `\0`. Key and value are seperated by `=`
    fn parse_attributes(attributes: &str) -> HashMap<String, String> {
        attributes
            .split('\0')
            .take_while(|kv_str| *kv_str != String::new())
            .map(|kv_str| {
                let mut iter = kv_str.split('=');
                let key = iter.next().unwrap();
                let value = iter.next().unwrap();
                (key.to_string(), value.to_string())
            })
            .collect()
    }

    /// Stores all driver description and attributes in a Vec
    pub fn drivers(&mut self) -> Result<Vec<DriverInfo>> {
        // Iterate twice, once for reading the maximum required buffer lengths so we can read
        // everything without truncating and a second time for actually storing the values
        // alloc_info iterates ones over every driver to obtain the requiered buffer sizes
        let (max_desc, max_attr, num_drivers) = self.alloc_info(
            safe::Environment::drivers,
            ffi::SQL_FETCH_FIRST,
        )?;

        let mut driver_list = Vec::with_capacity(num_drivers);
        let mut description_buffer = vec![0; (max_desc + 1) as usize];
        let mut attribute_buffer = vec![0; (max_attr + 1) as usize];
        while let Some((desc, attr)) =
            self.get_info(
                safe::Environment::drivers,
                ffi::SQL_FETCH_NEXT,
                &mut description_buffer,
                &mut attribute_buffer,
            )?
        {
            driver_list.push(DriverInfo {
                description: desc.to_owned(),
                attributes: Self::parse_attributes(attr),
            })
        }
        Ok(driver_list)
    }

    /// Stores all data source server names and descriptions in a Vec
    pub fn data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST)
    }

    /// Stores all sytem data source server names and descriptions in a Vec
    pub fn system_data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST_SYSTEM)
    }

    /// Stores all user data source server names and descriptions in a Vec
    pub fn user_data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST_USER)
    }

    /// Use SQL_FETCH_FIRST, SQL_FETCH_FIRST_USER or SQL_FETCH_FIRST_SYSTEM, to get all, user or
    /// system data sources
    fn data_sources_impl(
        &mut self,
        direction: ffi::FetchOrientation,
    ) -> Result<Vec<DataSourceInfo>> {

        // alloc_info iterates ones over every datasource to obtain the requiered buffer sizes
        let (max_name, max_desc, num_sources) =
            self.alloc_info(safe::Environment::data_sources, direction)?;

        let mut source_list = Vec::with_capacity(num_sources);
        let mut name_buffer: Vec<_> = (0..(max_name + 1)).map(|_| 0u8).collect();
        let mut description_buffer: Vec<_> = (0..(max_desc + 1)).map(|_| 0u8).collect();

        // Before we call SQLDataSources with SQL_FETCH_NEXT, we have to call it with either
        // SQL_FETCH_FIRST, SQL_FETCH_FIRST_USER or SQL_FETCH_FIRST_SYSTEM, to get all, user or
        // system data sources
        if let Some((name, desc)) =
            self.get_info(
                safe::Environment::data_sources,
                direction,
                &mut name_buffer,
                &mut description_buffer,
            )?
        {
            source_list.push(DataSourceInfo {
                server_name: name.to_owned(),
                driver: desc.to_owned(),
            })
        } else {
            return Ok(source_list);
        }

        while let Some((name, desc)) =
            self.get_info(
                safe::Environment::data_sources,
                ffi::SQL_FETCH_NEXT,
                &mut name_buffer,
                &mut description_buffer,
            )?
        {
            source_list.push(DataSourceInfo {
                server_name: name.to_owned(),
                driver: desc.to_owned(),
            })
        }
        Ok(source_list)
    }

    /// Calls either SQLDrivers or SQLDataSources with the two given buffers and parses the result
    /// into a `(&str,&str)`
    fn get_info<'a, 'b>(
        &mut self,
        f: SqlInfoMethod,
        direction: ffi::FetchOrientation,
        buf1: &'a mut [u8],
        buf2: &'b mut [u8],
    ) -> Result<Option<(&'a str, &'b str)>> {

        let result = f(&mut self.safe, direction, buf1, buf2);
        match try_into_option(result, self)? {
            Some((len1, len2)) => Ok(Some((
                from_utf8(&buf1[0..(len1 as usize)]).unwrap(),
                from_utf8(&buf2[0..(len2 as usize)]).unwrap(),
            ))),
            None => Ok(None),
        }
    }

    /// Finds the maximum size required for description buffers
    fn alloc_info(
        &mut self,
        f: SqlInfoMethod,
        direction: ffi::FetchOrientation,
    ) -> Result<(ffi::SQLSMALLINT, ffi::SQLSMALLINT, usize)> {
        let mut string_buf1 = [0; 0];
        let mut string_buf2 = [0; 0];
        let mut max1 = 0;
        let mut max2 = 0;
        let mut count = 0;

        let mut result = f(
            &mut self.safe,
            direction,
            &mut string_buf1,
            &mut string_buf2,
        );

        loop {

            match result {
                safe::ReturnOption::Success((buf1_length_out, buf2_length_out)) |
                safe::ReturnOption::Info((buf1_length_out, buf2_length_out)) => {
                    count += 1;
                    max1 = max(max1, buf1_length_out);
                    max2 = max(max2, buf2_length_out);
                }
                safe::ReturnOption::NoData(()) => break,
                safe::ReturnOption::Error(()) => {
                    let diag = self.get_diag_rec(1).unwrap_or_else(DiagnosticRecord::empty);
                    error!("{}", diag);
                    return Err(diag);
                }
            }

            result = f(
                &mut self.safe,
                ffi::SQL_FETCH_NEXT,
                &mut string_buf1,
                &mut string_buf2,
            )
        }

        Ok((max1, max2, count))
    }
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn parse_attributes() {
        let buffer = "APILevel=2\0ConnectFunctions=YYY\0CPTimeout=60\0DriverODBCVer=03.\
                      50\0FileUsage=0\0SQLLevel=1\0UsageCount=1\0\0";
        let attributes = Environment::parse_attributes(buffer);
        assert_eq!(attributes["APILevel"], "2");
        assert_eq!(attributes["ConnectFunctions"], "YYY");
        assert_eq!(attributes["CPTimeout"], "60");
        assert_eq!(attributes["DriverODBCVer"], "03.50");
        assert_eq!(attributes["FileUsage"], "0");
        assert_eq!(attributes["SQLLevel"], "1");
        assert_eq!(attributes["UsageCount"], "1");
    }
}
<commit_msg>Prevent error when no drivers/datasources<commit_after>use super::{safe, try_into_option, Environment, DiagnosticRecord, GetDiagRec, Result, Version3};
use ffi;
use std::collections::HashMap;
use std::str::from_utf8;
use std::cmp::max;

/// Holds name and description of a datasource
///
/// Can be obtained via `Environment::data_sources`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataSourceInfo {
    /// Name of the data source
    pub server_name: String,
    /// Description of the data source
    pub driver: String,
}

/// Struct holding information available on a driver.
///
/// Can be obtained via `Environment::drivers`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DriverInfo {
    /// Name of the odbc driver
    pub description: String,
    /// List of attributes of the odbc driver
    pub attributes: HashMap<String, String>,
}

type SqlInfoMethod = fn(&mut safe::Environment<safe::Odbc3>,
                        ffi::FetchOrientation,
                        &mut [u8],
                        &mut [u8])
                        -> safe::ReturnOption<(i16, i16)>;

impl Environment<Version3> {
    /// Called by drivers to pares list of attributes
    ///
    /// Key value pairs are seperated by `\0`. Key and value are seperated by `=`
    fn parse_attributes(attributes: &str) -> HashMap<String, String> {
        attributes
            .split('\0')
            .take_while(|kv_str| *kv_str != String::new())
            .map(|kv_str| {
                let mut iter = kv_str.split('=');
                let key = iter.next().unwrap();
                let value = iter.next().unwrap();
                (key.to_string(), value.to_string())
            })
            .collect()
    }

    /// Stores all driver description and attributes in a Vec
    pub fn drivers(&mut self) -> Result<Vec<DriverInfo>> {
        // Iterate twice, once for reading the maximum required buffer lengths so we can read
        // everything without truncating and a second time for actually storing the values
        // alloc_info iterates ones over every driver to obtain the requiered buffer sizes
        let (max_desc, max_attr, num_drivers) = self.alloc_info(
            safe::Environment::drivers,
            ffi::SQL_FETCH_FIRST,
        )?;

        let mut driver_list = Vec::with_capacity(num_drivers);

        if num_drivers > 0 {
            let mut description_buffer = vec![0; (max_desc + 1) as usize];
            let mut attribute_buffer = vec![0; (max_attr + 1) as usize];
            while let Some((desc, attr)) =
            self.get_info(
                safe::Environment::drivers,
                ffi::SQL_FETCH_NEXT,
                &mut description_buffer,
                &mut attribute_buffer,
            )?
                {
                    driver_list.push(DriverInfo {
                        description: desc.to_owned(),
                        attributes: Self::parse_attributes(attr),
                    })
                }
        }

        Ok(driver_list)
    }

    /// Stores all data source server names and descriptions in a Vec
    pub fn data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST)
    }

    /// Stores all sytem data source server names and descriptions in a Vec
    pub fn system_data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST_SYSTEM)
    }

    /// Stores all user data source server names and descriptions in a Vec
    pub fn user_data_sources(&mut self) -> Result<Vec<DataSourceInfo>> {
        self.data_sources_impl(ffi::SQL_FETCH_FIRST_USER)
    }

    /// Use SQL_FETCH_FIRST, SQL_FETCH_FIRST_USER or SQL_FETCH_FIRST_SYSTEM, to get all, user or
    /// system data sources
    fn data_sources_impl(
        &mut self,
        direction: ffi::FetchOrientation,
    ) -> Result<Vec<DataSourceInfo>> {

        // alloc_info iterates ones over every datasource to obtain the requiered buffer sizes
        let (max_name, max_desc, num_sources) =
            self.alloc_info(safe::Environment::data_sources, direction)?;

        let mut source_list = Vec::with_capacity(num_sources);

        if num_sources > 0 {
            let mut name_buffer: Vec<_> = (0..(max_name + 1)).map(|_| 0u8).collect();
            let mut description_buffer: Vec<_> = (0..(max_desc + 1)).map(|_| 0u8).collect();

            // Before we call SQLDataSources with SQL_FETCH_NEXT, we have to call it with either
            // SQL_FETCH_FIRST, SQL_FETCH_FIRST_USER or SQL_FETCH_FIRST_SYSTEM, to get all, user or
            // system data sources
            if let Some((name, desc)) =
            self.get_info(
                safe::Environment::data_sources,
                direction,
                &mut name_buffer,
                &mut description_buffer,
            )?
            {
                source_list.push(DataSourceInfo {
                    server_name: name.to_owned(),
                    driver: desc.to_owned(),
                })
            } else {
                return Ok(source_list);
            }

            while let Some((name, desc)) =
            self.get_info(
                safe::Environment::data_sources,
                ffi::SQL_FETCH_NEXT,
                &mut name_buffer,
                &mut description_buffer,
            )?
                {
                    source_list.push(DataSourceInfo {
                        server_name: name.to_owned(),
                        driver: desc.to_owned(),
                    })
                }
        }

        Ok(source_list)
    }

    /// Calls either SQLDrivers or SQLDataSources with the two given buffers and parses the result
    /// into a `(&str,&str)`
    fn get_info<'a, 'b>(
        &mut self,
        f: SqlInfoMethod,
        direction: ffi::FetchOrientation,
        buf1: &'a mut [u8],
        buf2: &'b mut [u8],
    ) -> Result<Option<(&'a str, &'b str)>> {
        let result = f(&mut self.safe, direction, buf1, buf2);
        match try_into_option(result, self)? {
            Some((len1, len2)) => Ok(Some((
                from_utf8(&buf1[0..(len1 as usize)]).unwrap(),
                from_utf8(&buf2[0..(len2 as usize)]).unwrap(),
            ))),
            None => Ok(None),
        }
    }

    /// Finds the maximum size required for description buffers
    fn alloc_info(
        &mut self,
        f: SqlInfoMethod,
        direction: ffi::FetchOrientation,
    ) -> Result<(ffi::SQLSMALLINT, ffi::SQLSMALLINT, usize)> {
        let mut string_buf1 = [0; 0];
        let mut string_buf2 = [0; 0];
        let mut max1 = 0;
        let mut max2 = 0;
        let mut count = 0;

        let mut result = f(
            &mut self.safe,
            direction,
            &mut string_buf1,
            &mut string_buf2,
        );

        loop {
            match result {
                safe::ReturnOption::Success((buf1_length_out, buf2_length_out)) |
                safe::ReturnOption::Info((buf1_length_out, buf2_length_out)) => {
                    count += 1;
                    max1 = max(max1, buf1_length_out);
                    max2 = max(max2, buf2_length_out);
                }
                safe::ReturnOption::NoData(()) => break,
                safe::ReturnOption::Error(()) => {
                    let diag = self.get_diag_rec(1).unwrap_or_else(DiagnosticRecord::empty);
                    error!("{}", diag);
                    return Err(diag);
                }
            }

            result = f(
                &mut self.safe,
                ffi::SQL_FETCH_NEXT,
                &mut string_buf1,
                &mut string_buf2,
            )
        }

        Ok((max1, max2, count))
    }
}

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

    #[test]
    fn parse_attributes() {
        let buffer = "APILevel=2\0ConnectFunctions=YYY\0CPTimeout=60\0DriverODBCVer=03.\
                      50\0FileUsage=0\0SQLLevel=1\0UsageCount=1\0\0";
        let attributes = Environment::parse_attributes(buffer);
        assert_eq!(attributes["APILevel"], "2");
        assert_eq!(attributes["ConnectFunctions"], "YYY");
        assert_eq!(attributes["CPTimeout"], "60");
        assert_eq!(attributes["DriverODBCVer"], "03.50");
        assert_eq!(attributes["FileUsage"], "0");
        assert_eq!(attributes["SQLLevel"], "1");
        assert_eq!(attributes["UsageCount"], "1");
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tuple to array conversion, IntoDimension, and related things

use std::ops::{Index, IndexMut};
use libnum::Zero;

use {Ix, Ix1, IxDyn, Dimension, Dim};
use super::DimPrivate;

/// $m: macro callback
/// $m is called with $arg and then the indices corresponding to the size argument
macro_rules! index {
    ($m:ident $arg:tt 0) => ($m!($arg));
    ($m:ident $arg:tt 1) => ($m!($arg 0));
    ($m:ident $arg:tt 2) => ($m!($arg 0 1));
    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2));
    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3));
    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4));
    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5));
    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6));
}

macro_rules! index_item {
    ($m:ident $arg:tt 0) => ();
    ($m:ident $arg:tt 1) => ($m!($arg 0););
    ($m:ident $arg:tt 2) => ($m!($arg 0 1););
    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2););
    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3););
    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4););
    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5););
    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6););
}

/// Convert a value into a dimension.
pub trait IntoDimension {
    type Dim: Dimension;
    fn into_dimension(self) -> Self::Dim;
}

impl IntoDimension for Ix {
    type Dim = Ix1;
    #[inline(always)]
    fn into_dimension(self) -> Ix1 { Ix1(self) }
}

impl<D> IntoDimension for D where D: Dimension {
    type Dim = D;
    #[inline(always)]
    fn into_dimension(self) -> Self { self }
}

impl IntoDimension for Vec<usize> {
    type Dim = IxDyn;
    #[inline(always)]
    fn into_dimension(self) -> Self::Dim { Dim::new(self) }
}

pub trait Convert {
    type To;
    fn convert(self) -> Self::To;
}

macro_rules! sub {
    ($_x:tt $y:tt) => ($y);
}

macro_rules! tuple_type {
    ([$T:ident] $($index:tt)*) => (
        ( $(sub!($index $T), )* )
    )
}

macro_rules! tuple_expr {
    ([$self_:expr] $($index:tt)*) => (
        ( $($self_[$index], )* )
    )
}

macro_rules! array_expr {
    ([$self_:expr] $($index:tt)*) => (
        [$($self_ . $index, )*]
    )
}

macro_rules! array_zero {
    ([] $($index:tt)*) => (
        [$(sub!($index 0), )*]
    )
}

macro_rules! tuple_to_array {
    ([] $($n:tt)*) => {
        $(
        impl Convert for [Ix; $n] {
            type To = index!(tuple_type [Ix] $n);
            fn convert(self) -> Self::To {
                index!(tuple_expr [self] $n)
            }
        }

        impl IntoDimension for [Ix; $n] {
            type Dim = Dim<[Ix; $n]>;
            #[inline(always)]
            fn into_dimension(self) -> Self::Dim {
                Dim::new(self)
            }
        }

        impl IntoDimension for index!(tuple_type [Ix] $n) {
            type Dim = Dim<[Ix; $n]>;
            #[inline(always)]
            fn into_dimension(self) -> Self::Dim {
                Dim::new(index!(array_expr [self] $n))
            }
        }

        impl Index<usize> for Dim<[Ix; $n]> {
            type Output = usize;
            #[inline(always)]
            fn index(&self, index: usize) -> &Self::Output {
                &self.ix()[index]
            }
        }

        impl IndexMut<usize> for Dim<[Ix; $n]> {
            #[inline(always)]
            fn index_mut(&mut self, index: usize) -> &mut Self::Output {
                &mut self.ixm()[index]
            }
        }

        impl Zero for Dim<[Ix; $n]> {
            #[inline]
            fn zero() -> Self {
                Dim::new(index!(array_zero [] $n))
            }
            fn is_zero(&self) -> bool {
                self.slice().iter().all(|x| *x == 0)
            }
        }

        )*
    }
}

index_item!(tuple_to_array [] 7);
<commit_msg>Avoid using macros in type position<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tuple to array conversion, IntoDimension, and related things

use std::ops::{Index, IndexMut};
use libnum::Zero;

use {Ix, Ix1, IxDyn, Dimension, Dim};
use super::DimPrivate;

/// $m: macro callback
/// $m is called with $arg and then the indices corresponding to the size argument
macro_rules! index {
    ($m:ident $arg:tt 0) => ($m!($arg));
    ($m:ident $arg:tt 1) => ($m!($arg 0));
    ($m:ident $arg:tt 2) => ($m!($arg 0 1));
    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2));
    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3));
    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4));
    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5));
    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6));
}

macro_rules! index_item_ix {
    ($m:ident $arg:tt 0) => ($m!($arg););
    ($m:ident $arg:tt 1) => ($m!($arg Ix););
    ($m:ident $arg:tt 2) => ($m!($arg Ix Ix););
    ($m:ident $arg:tt 3) => ($m!($arg Ix Ix Ix););
    ($m:ident $arg:tt 4) => ($m!($arg Ix Ix Ix Ix););
    ($m:ident $arg:tt 5) => ($m!($arg Ix Ix Ix Ix Ix););
    ($m:ident $arg:tt 6) => ($m!($arg Ix Ix Ix Ix Ix Ix););
    ($m:ident $arg:tt 7) => ($m!($arg Ix Ix Ix Ix Ix Ix Ix););
}

macro_rules! index_item {
    ($m:ident $arg:tt 0) => ($m!($arg););
    ($m:ident $arg:tt 1) => ($m!($arg 0););
    ($m:ident $arg:tt 2) => ($m!($arg 0 1););
    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2););
    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3););
    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4););
    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5););
    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6););
}

/// Convert a value into a dimension.
pub trait IntoDimension {
    type Dim: Dimension;
    fn into_dimension(self) -> Self::Dim;
}

impl IntoDimension for Ix {
    type Dim = Ix1;
    #[inline(always)]
    fn into_dimension(self) -> Ix1 { Ix1(self) }
}

impl<D> IntoDimension for D where D: Dimension {
    type Dim = D;
    #[inline(always)]
    fn into_dimension(self) -> Self { self }
}

impl IntoDimension for Vec<usize> {
    type Dim = IxDyn;
    #[inline(always)]
    fn into_dimension(self) -> Self::Dim { Dim::new(self) }
}

pub trait Convert {
    type To;
    fn convert(self) -> Self::To;
}

macro_rules! sub {
    ($_x:tt $y:tt) => ($y);
}

macro_rules! tuple_type {
    ([$T:ident] $($index:tt)*) => (
        ( $(sub!($index $T), )* )
    )
}

macro_rules! tuple_expr {
    ([$self_:expr] $($index:tt)*) => (
        ( $($self_[$index], )* )
    )
}

macro_rules! array_expr {
    ([$self_:expr] $($index:tt)*) => (
        [$($self_ . $index, )*]
    )
}

macro_rules! array_zero {
    ([] $($index:tt)*) => (
        [$(sub!($index 0), )*]
    )
}

macro_rules! tuple_to_array {
    ([] $($n:tt)*) => {
        $(
        index_item_ix!(impl_tuple_to_array [$n] $n);
        )*
    }
}
macro_rules! impl_tuple_to_array {
    ([$n:tt] $($ix:tt)*) => {
        impl Convert for [Ix; $n] {
            type To = ($($ix ,)*);
            fn convert(self) -> Self::To {
                index!(tuple_expr [self] $n)
            }
        }

        impl IntoDimension for [Ix; $n] {
            type Dim = Dim<[Ix; $n]>;
            #[inline(always)]
            fn into_dimension(self) -> Self::Dim {
                Dim::new(self)
            }
        }

        impl IntoDimension for ($($ix ,)*) {
            type Dim = Dim<[Ix; $n]>;
            #[inline(always)]
            fn into_dimension(self) -> Self::Dim {
                Dim::new(index!(array_expr [self] $n))
            }
        }

        impl Index<usize> for Dim<[Ix; $n]> {
            type Output = usize;
            #[inline(always)]
            fn index(&self, index: usize) -> &Self::Output {
                &self.ix()[index]
            }
        }

        impl IndexMut<usize> for Dim<[Ix; $n]> {
            #[inline(always)]
            fn index_mut(&mut self, index: usize) -> &mut Self::Output {
                &mut self.ixm()[index]
            }
        }

        impl Zero for Dim<[Ix; $n]> {
            #[inline]
            fn zero() -> Self {
                Dim::new(index!(array_zero [] $n))
            }
            fn is_zero(&self) -> bool {
                self.slice().iter().all(|x| *x == 0)
            }
        }
    }
}

index_item!(tuple_to_array [] 7);
<|endoftext|>


<commit_before>// https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/
pub fn num_submatrix_sum_target(matrix: Vec<Vec<i32>>, target: i32) -> i32 {
    todo!()
}

fn main() {
    println!(
        "{}",
        num_submatrix_sum_target(vec![vec![0, 1, 0], vec![1, 1, 1], vec![0, 1, 0]], 0)
    ); // 4
    println!(
        "{}",
        num_submatrix_sum_target(vec![vec![1, -1], vec![-1, 1]], 0)
    ); // 5
    println!("{}", num_submatrix_sum_target(vec![vec![904]], 0)); // 0
}
<commit_msg>Update problem 1074<commit_after>// https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/
pub fn num_submatrix_sum_target(matrix: Vec<Vec<i32>>, target: i32) -> i32 {
    let mut answer = 0;
    let max_rows = matrix.len();
    let max_cols = if max_rows > 0 { matrix[0].len() } else { 0 };
    answer
}

fn main() {
    println!(
        "{}",
        num_submatrix_sum_target(vec![vec![0, 1, 0], vec![1, 1, 1], vec![0, 1, 0]], 0)
    ); // 4
    println!(
        "{}",
        num_submatrix_sum_target(vec![vec![1, -1], vec![-1, 1]], 0)
    ); // 5
    println!("{}", num_submatrix_sum_target(vec![vec![904]], 0)); // 0
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/most-frequent-even-element/
pub fn most_frequent_even(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", most_frequent_even(vec![0, 1, 2, 2, 4, 4, 1])); // 2
    println!("{}", most_frequent_even(vec![4, 4, 4, 9, 2, 4])); // 4
    println!(
        "{}",
        most_frequent_even(vec![29, 47, 21, 41, 13, 37, 25, 7])
    ); // -1
}
<commit_msg>Solve problem 2404<commit_after>use std::cmp::Ordering;
use std::collections::HashMap;

// https://leetcode.com/problems/most-frequent-even-element/
pub fn most_frequent_even(nums: Vec<i32>) -> i32 {
    let mut map: HashMap<i32, i32> = HashMap::new();
    for num in nums.into_iter() {
        if num % 2 == 0 {
            *map.entry(num).or_insert(0) += 1;
        }
    }
    if map.is_empty() {
        -1
    } else {
        *map.iter()
            .max_by(|a, b| match a.1.cmp(b.1) {
                Ordering::Equal => b.0.cmp(a.0),
                _ => a.1.cmp(b.1),
            })
            .unwrap()
            .0
    }
}

fn main() {
    println!("{}", most_frequent_even(vec![0, 1, 2, 2, 4, 4, 1])); // 2
    println!("{}", most_frequent_even(vec![4, 4, 4, 9, 2, 4])); // 4
    println!(
        "{}",
        most_frequent_even(vec![29, 47, 21, 41, 13, 37, 25, 7])
    ); // -1
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/count-number-of-distinct-integers-after-reverse-operations/
pub fn count_distinct_integers(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", count_distinct_integers(vec![1, 13, 10, 12, 31])); // 6
    println!("{}", count_distinct_integers(vec![2, 2, 2])); // 1
}
<commit_msg>Solve problem 2442<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/count-number-of-distinct-integers-after-reverse-operations/
pub fn count_distinct_integers(nums: Vec<i32>) -> i32 {
    let mut set: HashSet<i32> = nums.iter().cloned().collect();
    for num in nums.into_iter() {
        let n: i32 = format!("{}", num)
            .chars()
            .rev()
            .collect::<String>()
            .parse()
            .unwrap();
        set.insert(n);
    }
    set.len() as i32
}

fn main() {
    println!("{}", count_distinct_integers(vec![1, 13, 10, 12, 31])); // 6
    println!("{}", count_distinct_integers(vec![2, 2, 2])); // 1
}
<|endoftext|>


<commit_before>//! Traits for abstracting away frame allocation and deallocation.

use crate::structures::paging::{PageSize, PhysFrame, Size4KiB};
use core::ops::{Deref, DerefMut};

/// A trait for types that can allocate a frame of memory.
///
/// This trait is unsafe to implement because the implementer must guarantee that
/// the `allocate_frame` method returns only unique unused frames.
pub unsafe trait FrameAllocator<S: PageSize> {
    /// Allocate a frame of the appropriate size and return it if possible.
    fn allocate_frame(&mut self) -> Option<PhysFrame<S>>;
}

/// A trait for types that can deallocate a frame of memory.
pub trait FrameDeallocator<S: PageSize> {
    /// Deallocate the given frame of memory.
    fn deallocate_frame(&mut self, frame: PhysFrame<S>);
}

/// Represents a physical frame that is not used for any mapping.
#[deprecated(note = "This wrapper type is no longer used. Use `PhysFrame` instead.")]
#[derive(Debug)]
pub struct UnusedPhysFrame<S: PageSize = Size4KiB>(PhysFrame<S>);

#[allow(deprecated)]
impl<S: PageSize> UnusedPhysFrame<S> {
    /// Creates a new UnusedPhysFrame from the given frame.
    ///
    /// ## Safety
    ///
    /// This method is unsafe because the caller must guarantee
    /// that the given frame is unused.
    #[inline]
    pub unsafe fn new(frame: PhysFrame<S>) -> Self {
        Self(frame)
    }

    /// Returns the physical frame as `PhysFrame` type.
    #[inline]
    pub fn frame(self) -> PhysFrame<S> {
        self.0
    }
}

#[allow(deprecated)]
impl<S: PageSize> Deref for UnusedPhysFrame<S> {
    type Target = PhysFrame<S>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[allow(deprecated)]
impl<S: PageSize> DerefMut for UnusedPhysFrame<S> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
<commit_msg>Make FrameDeallocator::deallocate_frame unsafe (#146)<commit_after>//! Traits for abstracting away frame allocation and deallocation.

use crate::structures::paging::{PageSize, PhysFrame, Size4KiB};
use core::ops::{Deref, DerefMut};

/// A trait for types that can allocate a frame of memory.
///
/// This trait is unsafe to implement because the implementer must guarantee that
/// the `allocate_frame` method returns only unique unused frames.
pub unsafe trait FrameAllocator<S: PageSize> {
    /// Allocate a frame of the appropriate size and return it if possible.
    fn allocate_frame(&mut self) -> Option<PhysFrame<S>>;
}

/// A trait for types that can deallocate a frame of memory.
pub trait FrameDeallocator<S: PageSize> {
    /// Deallocate the given unused frame.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that the passed frame is unused.
    unsafe fn deallocate_frame(&mut self, frame: PhysFrame<S>);
}

/// Represents a physical frame that is not used for any mapping.
#[deprecated(note = "This wrapper type is no longer used. Use `PhysFrame` instead.")]
#[derive(Debug)]
pub struct UnusedPhysFrame<S: PageSize = Size4KiB>(PhysFrame<S>);

#[allow(deprecated)]
impl<S: PageSize> UnusedPhysFrame<S> {
    /// Creates a new UnusedPhysFrame from the given frame.
    ///
    /// ## Safety
    ///
    /// This method is unsafe because the caller must guarantee
    /// that the given frame is unused.
    #[inline]
    pub unsafe fn new(frame: PhysFrame<S>) -> Self {
        Self(frame)
    }

    /// Returns the physical frame as `PhysFrame` type.
    #[inline]
    pub fn frame(self) -> PhysFrame<S> {
        self.0
    }
}

#[allow(deprecated)]
impl<S: PageSize> Deref for UnusedPhysFrame<S> {
    type Target = PhysFrame<S>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[allow(deprecated)]
impl<S: PageSize> DerefMut for UnusedPhysFrame<S> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
<|endoftext|>


<commit_before>extern mod extra;
use extra::container::Deque;
use extra::ringbuf::RingBuf;
use std::iter::Peekable;
#[deriving(Clone, Eq, ToStr)]
pub enum TokenEnum {
	EOF,
	NAME,
	OPERATOR,
	NUMBER,
	FLOAT,
	LPARENS,
	RPARENS,
	LBRACKET,
	RBRACKET,
	LBRACE,
	RBRACE,
	INDENTSTART,
	INDENTLEVEL,
	COMMA,
	EQUALSSIGN,
	SEMICOLON,
	MODULE,
	CLASS,
	INSTANCE,
	WHERE,
	LET,
	IN,
	CASE,
	OF,
	ARROW,
	TYPEDECL,
	DATA
}

#[deriving(Clone, Eq, ToStr)]
pub struct Location {
    column : int,
    row : int,
    absolute : int
}

#[deriving(Clone)]
pub struct Token {
    token : TokenEnum,
    value : ~str,
    location : Location
}
impl Token {
    fn eof() -> Token {
        Token { token : EOF, value : ~"", location : Location { column : -1, row : -1, absolute : -1} }
    }

    fn new(token : TokenEnum, value : ~str, loc : Location) -> Token {
        Token { token : token, value : value, location : loc }
    }
    fn new_(token : TokenEnum, value : ~str) -> Token {
        Token::new(token, value, Location { column : -1, row : -1, absolute : -1 })
    }
}

impl Eq for Token {
    fn eq(&self, rhs : &Token) -> bool {
        self.token == rhs.token && self.value == rhs.value
    }
}

fn name_or_keyword(tok : &str) -> TokenEnum {
    match tok {
        "module" => MODULE,
        "class" => CLASS,
        "instance" => INSTANCE,
        "where" => WHERE,
        "let" => LET,
        "in" => IN,
        "case" => CASE,
        "of" => OF,
        "->" => ARROW,
        "data" => DATA,
        _ => NAME
    }
}

fn is_operator(first_char : char) -> bool {
    match first_char {
        '+' => true,
        '-' => true,
        '*' => true,
        '/' => true,
        '.' => true,
        '$' => true,
        ':' => true,
        '=' => true,
        '<' => true,
        '>' => true,
        '|' => true,
        '&' => true,
        _ => false
    }
}

pub struct Lexer<Stream> {
    priv input : Peekable<char, Stream>,
    priv location : Location,
    priv previousLocation : Location,
    priv unprocessedTokens : ~[Token],
    priv tokens : extra::ringbuf::RingBuf<Token>,
    priv indentLevels : ~[int],
    priv offset : uint
}

impl <Stream : Iterator<char>> Lexer<Stream> {

    pub fn new(input : Stream) -> Lexer<Stream> {
        let start = Location { column : 0, row : 0, absolute : 0};
        Lexer {
            input : input.peekable(),
            location : start,
            previousLocation : start,
            unprocessedTokens : ~[],
            tokens : extra::ringbuf::RingBuf::with_capacity(20),
            indentLevels : ~[],
            offset : 0}
    }

    pub fn next_<'a>(&'a mut self) -> &'a Token {
        self.next(|_| false)
    }
    pub fn next<'a>(&'a mut self, parseError : |&Token| -> bool) -> &'a Token {
        if self.offset > 0 {
            match self.tokens.iter().idx(self.tokens.len() - 1 - self.offset) {
                Some(token) => {
                    self.offset -= 1;
                    token
                }
                None => fail!("Impossible empty tokens stream")
            }
        }
        else if self.unprocessedTokens.len() > 0 {
            self.layout_independent_token(parseError);
            self.tokens.back().unwrap()
        }
        else {
            self.new_token(parseError)
        }
    }

    pub fn current<'a>(&'a self) -> &'a Token {
        match self.tokens.iter().idx(self.tokens.len() - 1 - self.offset) {
            Some(token) => token,
            None => fail!("Attempted to access Lexer::current() on when tokens is empty")
        }
    }

    pub fn backtrack(&mut self) {
        self.offset += 1;
    }

    pub fn valid(&self) -> bool {
        self.offset > 0 || match self.tokens.back() { None => true, Some(x) => x.token != EOF }
    }

    fn peek(&mut self) -> Option<char> {
        match self.input.peek() {
            Some(ch) => Some(*ch),
            None => None
        }
    }

    fn read_char(&mut self) -> Option<char> {
        match self.input.next() {
            Some(c) => {
                self.location = self.location;
                self.location.absolute += 1;
                self.location.column += 1;
                if (c == '\n' || c == '\r')
                {
                    self.location.column = 0;
                    self.location.row += 1;
                }
                Some(c)
            }
            None => None
        }
    }

    fn scan_digits(&mut self) -> ~str {
        let mut result = ~"";
        loop {
            match self.peek() {
                Some(x) => {
                    if !x.is_digit() {
                        return result;
                    }
                    self.read_char();
                    result.push_char(x)
                }
                None => return result
            }
        }
        result
    }

    fn scan_number(&mut self, c : char, location : Location) -> Token {
        let mut number = c.to_str() + self.scan_digits();
        let mut token = NUMBER;
        match self.peek() {
            Some('.') => {
                token = FLOAT;
                number.push_char('.');
                number = number.append(self.scan_digits());
            }
            _ => ()
        }
        Token { token : NUMBER, value : number, location : location }
    }

    fn new_token<'a>(&'a mut self, parseError : |&Token| -> bool) -> &'a Token {
        let mut newline = false;
        let n = self.next_indent_token(&mut newline);
        self.unprocessedTokens.push(n);
        let newTok = self.unprocessedTokens[self.unprocessedTokens.len() - 1].token;

        if newTok != LBRACE {
            match self.tokens.back() {
                Some(tok) => {
                    if tok.token == LET || tok.token == WHERE || tok.token == OF {
                        let loc = self.unprocessedTokens[self.unprocessedTokens.len() - 1].location;
                        let indentstart = Token { token : INDENTSTART, value : ~"{n}", location : loc };
                        self.unprocessedTokens.push(indentstart);
                    }
                }
                None => ()
            }
        }
        if newline {
            self.unprocessedTokens.push(Token::new(INDENTLEVEL, ~"<n>", self.location));
        }
        self.layout_independent_token(parseError);
        self.tokens.back().unwrap()
    }

    fn layout_independent_token(&mut self, parseError : |&Token| -> bool) {
        if self.unprocessedTokens.len() > 0 {
            let tok = self.unprocessedTokens[self.unprocessedTokens.len() - 1].clone();//TODO dont use clone
            match tok.token {
                INDENTLEVEL => {
                    if (self.indentLevels.len() > 0) {
                        //m:ms
                        let m = self.indentLevels[self.indentLevels.len() - 1];
                        //m == n
                        if (m == tok.location.column) {
                            self.tokens.push_back(Token::new(SEMICOLON, ~";", tok.location));
                            self.unprocessedTokens.pop();
                            return;
                        }
                        else if (tok.location.column < m)// n < m
                        {
                            //TODO
                            self.indentLevels.pop();
                            self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                            return;
                        }
                    }
                    self.unprocessedTokens.pop();
                    if (self.unprocessedTokens.len() == 0) {
                        debug!("Skipping to next");
                        self.new_token(parseError);
                        return;
                    }
                    else {
                        return self.layout_independent_token(parseError);
                    }
                }
                INDENTSTART => {
                    //{n} token
                    let n = tok.location.column;
                    if (self.indentLevels.len() != 0) {
                        //m:ms
                        let m = self.indentLevels[self.indentLevels.len() - 1];
                        if (n > m) {
                            self.unprocessedTokens.pop();
                            self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                            self.indentLevels.push(n);
                            return;
                        }
                    }
                    if (n > 0)
                    {
                        self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                        self.unprocessedTokens.pop();
                        self.indentLevels.push(n);
                        return;
                    }
                    self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                    self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                    self.unprocessedTokens.pop();
                    self.unprocessedTokens.push(Token::new(INDENTLEVEL, ~"<n>", tok.location));
                    self.offset += 1;
                    return;
                }
                RBRACE => {
                    if (self.indentLevels.len() > 0 && self.indentLevels[self.indentLevels.len()] == 0) {
                        self.tokens.push_back(self.unprocessedTokens.pop());
                        self.indentLevels.pop();
                        return;
                    }
                    else {
                        return;//parse-error
                    }
                }
                LBRACE => {
                    self.tokens.push_back(self.unprocessedTokens.pop());
                    self.indentLevels.push(0);
                    return;
                }

                _ => ()
            }
            if (self.indentLevels.len() != 0) {
                //L (t:ts) (m:ms) 	= 	} : (L (t:ts) ms) 	if m /= 0 and parse-error(t)
                let m = self.indentLevels[self.indentLevels.len() - 1];
                if (m != 0 && parseError(&tok))
                {
                    self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                    self.indentLevels.pop();
                    return;
                }
            }
            self.tokens.push_back(self.unprocessedTokens.pop());
            return;
        }
        else {
            if (self.indentLevels.len() == 0)//End of stream
            {
                return;
            }
            else if (self.indentLevels[self.indentLevels.len() - 1] != 0)//Keep pusing righ brackets
            {
                self.indentLevels.pop();
                self.tokens.push_back(Token::new_(RBRACE, ~"}"));
                return;
            }
        }
    }

    fn next_indent_token(&mut self, newline : &mut bool) -> Token {
        let mut c = ' ';
        //Skip all whitespace before the token
        while c.is_whitespace() {
            match self.read_char() {
                Some(x) => {
                    c = x;
                    if (self.location.column == 0)//newline detected
                    {
                        *newline = true;
                    }
                }
                None => { return Token::eof() }
            }
        }
        let startLocation = self.location;

        //Decide how to tokenize depending on what the first char is
        //ie if its an operator then more operators will follow
        if (is_operator(c))
        {
            let mut result = c.to_str();
            loop {
                match self.peek() {
                    Some(ch) => {
                        if !is_operator(ch) {
                            break;
                        }
                        self.read_char();
                        result.push_char(ch);
                    }
                    None => { break; }
                }
            }
            let tok = match result {
                ~"="  => EQUALSSIGN,
                ~"->" => ARROW,
                ~"::" => TYPEDECL,
                _    => OPERATOR
            };
            return Token { token : tok, value : result, location : startLocation };
        }
        else if (c.is_digit())
        {
            return self.scan_number(c, startLocation);
        }
        else if (c.is_alphabetic() || c == '_')
        {
            let mut result = c.to_str();
            loop {
                match self.peek() {
                    Some(ch) => {
                        if !ch.is_alphanumeric() && ch != '_' {
                            break;
                        }
                        self.read_char();
                        result.push_char(ch);
                    }
                    None => return Token::eof()
                }
            }
            return Token {
                token : name_or_keyword(result),
                location : startLocation,
                value : result};
        }
        let tok = match c {
            ';' => SEMICOLON,
            '(' => LPARENS,
            ')' => RPARENS,
            '[' => LBRACKET,
            ']' => RBRACKET,
            '{' => LBRACE,
            '}' => RBRACE,
            ',' => COMMA,
            _   => EOF
        };
        Token { token : tok, location : startLocation, value : c.to_str() }
    }
}

#[test]
fn simple() {
    let mut lexer = Lexer::new("test 2 + 3".chars());

    assert_eq!(*lexer.next_(), Token::new_(NAME, ~"test"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"2"));
    assert_eq!(*lexer.next_(), Token::new_(OPERATOR, ~"+"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"3"));
}
#[test]
fn let_bind() {
    let mut lexer = Lexer::new(
r"let
    test = 2 + 3
in test".chars());

    assert_eq!(*lexer.next_(), Token::new_(LET, ~"let"));
    assert_eq!(*lexer.next_(), Token::new_(LBRACE, ~"{"));
    assert_eq!(*lexer.next_(), Token::new_(NAME, ~"test"));
    assert_eq!(*lexer.next_(), Token::new_(EQUALSSIGN, ~"="));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"2"));
    assert_eq!(*lexer.next_(), Token::new_(OPERATOR, ~"+"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"3"));
}
<commit_msg>Added module_next to parse the first token of a module<commit_after>extern mod extra;
use extra::container::Deque;
use extra::ringbuf::RingBuf;
use std::iter::Peekable;
#[deriving(Clone, Eq, ToStr)]
pub enum TokenEnum {
	EOF,
	NAME,
	OPERATOR,
	NUMBER,
	FLOAT,
	LPARENS,
	RPARENS,
	LBRACKET,
	RBRACKET,
	LBRACE,
	RBRACE,
	INDENTSTART,
	INDENTLEVEL,
	COMMA,
	EQUALSSIGN,
	SEMICOLON,
	MODULE,
	CLASS,
	INSTANCE,
	WHERE,
	LET,
	IN,
	CASE,
	OF,
	ARROW,
	TYPEDECL,
	DATA
}

#[deriving(Clone, Eq, ToStr)]
pub struct Location {
    column : int,
    row : int,
    absolute : int
}

#[deriving(Clone)]
pub struct Token {
    token : TokenEnum,
    value : ~str,
    location : Location
}
impl Token {
    fn eof() -> Token {
        Token { token : EOF, value : ~"", location : Location { column : -1, row : -1, absolute : -1} }
    }

    fn new(token : TokenEnum, value : ~str, loc : Location) -> Token {
        Token { token : token, value : value, location : loc }
    }
    fn new_(token : TokenEnum, value : ~str) -> Token {
        Token::new(token, value, Location { column : -1, row : -1, absolute : -1 })
    }
}

impl Eq for Token {
    fn eq(&self, rhs : &Token) -> bool {
        self.token == rhs.token && self.value == rhs.value
    }
}

fn name_or_keyword(tok : &str) -> TokenEnum {
    match tok {
        "module" => MODULE,
        "class" => CLASS,
        "instance" => INSTANCE,
        "where" => WHERE,
        "let" => LET,
        "in" => IN,
        "case" => CASE,
        "of" => OF,
        "->" => ARROW,
        "data" => DATA,
        _ => NAME
    }
}

fn is_operator(first_char : char) -> bool {
    match first_char {
        '+' => true,
        '-' => true,
        '*' => true,
        '/' => true,
        '.' => true,
        '$' => true,
        ':' => true,
        '=' => true,
        '<' => true,
        '>' => true,
        '|' => true,
        '&' => true,
        _ => false
    }
}

pub struct Lexer<Stream> {
    priv input : Peekable<char, Stream>,
    priv location : Location,
    priv previousLocation : Location,
    priv unprocessedTokens : ~[Token],
    priv tokens : extra::ringbuf::RingBuf<Token>,
    priv indentLevels : ~[int],
    priv offset : uint
}

impl <Stream : Iterator<char>> Lexer<Stream> {

    pub fn new(input : Stream) -> Lexer<Stream> {
        let start = Location { column : 0, row : 0, absolute : 0};
        Lexer {
            input : input.peekable(),
            location : start,
            previousLocation : start,
            unprocessedTokens : ~[],
            tokens : extra::ringbuf::RingBuf::with_capacity(20),
            indentLevels : ~[],
            offset : 0}
    }
    pub fn module_next<'a>(&'a mut self) -> &'a Token {
        let mut newline = false;
        let n = self.next_indent_token(&mut newline);
        self.unprocessedTokens.push(n);
        let newTok = self.unprocessedTokens[self.unprocessedTokens.len() - 1].token;

        if newTok != LBRACE && newTok != MODULE {
            self.unprocessedTokens.push(Token::new(INDENTSTART, ~"{n}", self.location));
        }
        if newline {
            self.unprocessedTokens.push(Token::new(INDENTLEVEL, ~"<n>", self.location));
        }

        self.layout_independent_token(|_| false);
        self.current()
    }

    pub fn next_<'a>(&'a mut self) -> &'a Token {
        self.next(|_| false)
    }
    pub fn next<'a>(&'a mut self, parseError : |&Token| -> bool) -> &'a Token {
        if self.offset > 0 {
            match self.tokens.iter().idx(self.tokens.len() - 1 - self.offset) {
                Some(token) => {
                    self.offset -= 1;
                    token
                }
                None => fail!("Impossible empty tokens stream")
            }
        }
        else if self.unprocessedTokens.len() > 0 {
            self.layout_independent_token(parseError);
            self.tokens.back().unwrap()
        }
        else {
            self.new_token(parseError)
        }
    }

    pub fn current<'a>(&'a self) -> &'a Token {
        match self.tokens.iter().idx(self.tokens.len() - 1 - self.offset) {
            Some(token) => token,
            None => fail!("Attempted to access Lexer::current() on when tokens is empty")
        }
    }

    pub fn backtrack(&mut self) {
        self.offset += 1;
    }

    pub fn valid(&self) -> bool {
        self.offset > 0 || match self.tokens.back() { None => true, Some(x) => x.token != EOF }
    }

    fn peek(&mut self) -> Option<char> {
        match self.input.peek() {
            Some(ch) => Some(*ch),
            None => None
        }
    }

    fn read_char(&mut self) -> Option<char> {
        match self.input.next() {
            Some(c) => {
                self.location = self.location;
                self.location.absolute += 1;
                self.location.column += 1;
                if (c == '\n' || c == '\r')
                {
                    self.location.column = 0;
                    self.location.row += 1;
                }
                Some(c)
            }
            None => None
        }
    }

    fn scan_digits(&mut self) -> ~str {
        let mut result = ~"";
        loop {
            match self.peek() {
                Some(x) => {
                    if !x.is_digit() {
                        return result;
                    }
                    self.read_char();
                    result.push_char(x)
                }
                None => return result
            }
        }
        result
    }

    fn scan_number(&mut self, c : char, location : Location) -> Token {
        let mut number = c.to_str() + self.scan_digits();
        let mut token = NUMBER;
        match self.peek() {
            Some('.') => {
                token = FLOAT;
                number.push_char('.');
                number = number.append(self.scan_digits());
            }
            _ => ()
        }
        Token { token : NUMBER, value : number, location : location }
    }

    fn new_token<'a>(&'a mut self, parseError : |&Token| -> bool) -> &'a Token {
        let mut newline = false;
        let n = self.next_indent_token(&mut newline);
        self.unprocessedTokens.push(n);
        let newTok = self.unprocessedTokens[self.unprocessedTokens.len() - 1].token;

        if newTok != LBRACE {
            match self.tokens.back() {
                Some(tok) => {
                    if tok.token == LET || tok.token == WHERE || tok.token == OF {
                        let loc = self.unprocessedTokens[self.unprocessedTokens.len() - 1].location;
                        let indentstart = Token { token : INDENTSTART, value : ~"{n}", location : loc };
                        self.unprocessedTokens.push(indentstart);
                    }
                }
                None => ()
            }
        }
        if newline {
            self.unprocessedTokens.push(Token::new(INDENTLEVEL, ~"<n>", self.location));
        }
        self.layout_independent_token(parseError);
        self.tokens.back().unwrap()
    }

    fn layout_independent_token(&mut self, parseError : |&Token| -> bool) {
        if self.unprocessedTokens.len() > 0 {
            let tok = self.unprocessedTokens[self.unprocessedTokens.len() - 1].clone();//TODO dont use clone
            match tok.token {
                INDENTLEVEL => {
                    if (self.indentLevels.len() > 0) {
                        //m:ms
                        let m = self.indentLevels[self.indentLevels.len() - 1];
                        //m == n
                        if (m == tok.location.column) {
                            self.tokens.push_back(Token::new(SEMICOLON, ~";", tok.location));
                            self.unprocessedTokens.pop();
                            return;
                        }
                        else if (tok.location.column < m)// n < m
                        {
                            //TODO
                            self.indentLevels.pop();
                            self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                            return;
                        }
                    }
                    self.unprocessedTokens.pop();
                    if (self.unprocessedTokens.len() == 0) {
                        debug!("Skipping to next");
                        self.new_token(parseError);
                        return;
                    }
                    else {
                        return self.layout_independent_token(parseError);
                    }
                }
                INDENTSTART => {
                    //{n} token
                    let n = tok.location.column;
                    if (self.indentLevels.len() != 0) {
                        //m:ms
                        let m = self.indentLevels[self.indentLevels.len() - 1];
                        if (n > m) {
                            self.unprocessedTokens.pop();
                            self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                            self.indentLevels.push(n);
                            return;
                        }
                    }
                    if (n > 0)
                    {
                        self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                        self.unprocessedTokens.pop();
                        self.indentLevels.push(n);
                        return;
                    }
                    self.tokens.push_back(Token::new(LBRACE, ~"{", tok.location));
                    self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                    self.unprocessedTokens.pop();
                    self.unprocessedTokens.push(Token::new(INDENTLEVEL, ~"<n>", tok.location));
                    self.offset += 1;
                    return;
                }
                RBRACE => {
                    if (self.indentLevels.len() > 0 && self.indentLevels[self.indentLevels.len()] == 0) {
                        self.tokens.push_back(self.unprocessedTokens.pop());
                        self.indentLevels.pop();
                        return;
                    }
                    else {
                        return;//parse-error
                    }
                }
                LBRACE => {
                    self.tokens.push_back(self.unprocessedTokens.pop());
                    self.indentLevels.push(0);
                    return;
                }

                _ => ()
            }
            if (self.indentLevels.len() != 0) {
                //L (t:ts) (m:ms) 	= 	} : (L (t:ts) ms) 	if m /= 0 and parse-error(t)
                let m = self.indentLevels[self.indentLevels.len() - 1];
                if (m != 0 && parseError(&tok))
                {
                    self.tokens.push_back(Token::new(RBRACE, ~"}", tok.location));
                    self.indentLevels.pop();
                    return;
                }
            }
            self.tokens.push_back(self.unprocessedTokens.pop());
            return;
        }
        else {
            if (self.indentLevels.len() == 0)//End of stream
            {
                return;
            }
            else if (self.indentLevels[self.indentLevels.len() - 1] != 0)//Keep pusing righ brackets
            {
                self.indentLevels.pop();
                self.tokens.push_back(Token::new_(RBRACE, ~"}"));
                return;
            }
        }
    }

    fn next_indent_token(&mut self, newline : &mut bool) -> Token {
        let mut c = ' ';
        //Skip all whitespace before the token
        while c.is_whitespace() {
            match self.read_char() {
                Some(x) => {
                    c = x;
                    if (self.location.column == 0)//newline detected
                    {
                        *newline = true;
                    }
                }
                None => { return Token::eof() }
            }
        }
        let startLocation = self.location;

        //Decide how to tokenize depending on what the first char is
        //ie if its an operator then more operators will follow
        if (is_operator(c))
        {
            let mut result = c.to_str();
            loop {
                match self.peek() {
                    Some(ch) => {
                        if !is_operator(ch) {
                            break;
                        }
                        self.read_char();
                        result.push_char(ch);
                    }
                    None => { break; }
                }
            }
            let tok = match result {
                ~"="  => EQUALSSIGN,
                ~"->" => ARROW,
                ~"::" => TYPEDECL,
                _    => OPERATOR
            };
            return Token { token : tok, value : result, location : startLocation };
        }
        else if (c.is_digit())
        {
            return self.scan_number(c, startLocation);
        }
        else if (c.is_alphabetic() || c == '_')
        {
            let mut result = c.to_str();
            loop {
                match self.peek() {
                    Some(ch) => {
                        if !ch.is_alphanumeric() && ch != '_' {
                            break;
                        }
                        self.read_char();
                        result.push_char(ch);
                    }
                    None => return Token::eof()
                }
            }
            return Token {
                token : name_or_keyword(result),
                location : startLocation,
                value : result};
        }
        let tok = match c {
            ';' => SEMICOLON,
            '(' => LPARENS,
            ')' => RPARENS,
            '[' => LBRACKET,
            ']' => RBRACKET,
            '{' => LBRACE,
            '}' => RBRACE,
            ',' => COMMA,
            _   => EOF
        };
        Token { token : tok, location : startLocation, value : c.to_str() }
    }
}

#[test]
fn simple() {
    let mut lexer = Lexer::new("test 2 + 3".chars());

    assert_eq!(*lexer.next_(), Token::new_(NAME, ~"test"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"2"));
    assert_eq!(*lexer.next_(), Token::new_(OPERATOR, ~"+"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"3"));
}
#[test]
fn let_bind() {
    let mut lexer = Lexer::new(
r"let
    test = 2 + 3
in test".chars());

    assert_eq!(*lexer.next_(), Token::new_(LET, ~"let"));
    assert_eq!(*lexer.next_(), Token::new_(LBRACE, ~"{"));
    assert_eq!(*lexer.next_(), Token::new_(NAME, ~"test"));
    assert_eq!(*lexer.next_(), Token::new_(EQUALSSIGN, ~"="));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"2"));
    assert_eq!(*lexer.next_(), Token::new_(OPERATOR, ~"+"));
    assert_eq!(*lexer.next_(), Token::new_(NUMBER, ~"3"));
}
<|endoftext|>


<commit_before>use super::expr::Expression;
use super::{CompileError, is_truthy};
use super::scope::Scope;
use super::sum::Sum;

#[cfg(test)]
use super::lexer;
#[cfg(test)]
use super::{TRUE, FALSE};

// Something that can be called with arguments given in the scope
pub trait Function {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError>;
}

macro_rules! bind_function(
    ( $name:ident, $func:ident ( $($arg:ident),* ) ) => (
		struct $name;
		impl $name {
			fn new() -> $name {
				$name
			}
		}
		impl Function for $name {
			#[allow(unused_variables)] // Compiler complains that scope is not used on functions with no args.
			fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
				Ok($func($(
					// Insert each argument from the scope
					match scope.var_id(stringify!($arg)) {
						Some(id) => scope.get_var(id).unwrap(),

						None => return Err(CompileError {
							msg: format!("function `{}` requires argument `{}` but it is not defined in scope", stringify!($func), stringify!($arg)),
							pos: None }),
					}
				),*))
			}
		}
    );
)

fn sin(a: f32) -> f32 {
	a.sin()
}

bind_function!(SinFunction, sin(a))

// Always returns a specific constant
struct ConstFunction {
	val: f32,
}
impl ConstFunction {
	fn new(val: f32) -> ConstFunction {
		ConstFunction {
			val: val,
		}
	}
}
impl Function for ConstFunction {
	fn call(&self, _: &Scope) -> Result<f32, CompileError> {
		Ok(self.val)
	}
}

// Wraps an expression from the expr module.
struct ExprFunction<'a> {
	expr: &'a Expression<'a>,
}
impl<'a> ExprFunction<'a> {
	fn new(expr: &'a Expression<'a>) -> ExprFunction<'a> {
		ExprFunction {
			expr: expr,
		}
	}
}
impl<'a> Function for ExprFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		self.expr.eval(scope)
	}
}

// Returns the result of calling the function if the condition is truthy, else 0
struct CondFunction<'a> {
	cond: Box<Function + 'a>,
	func: Box<Function + 'a>,
}
impl<'a> CondFunction<'a> {
	fn new(cond: Box<Function + 'a>, func: Box<Function + 'a>) -> CondFunction<'a> {
		CondFunction {
			cond: cond,
			func: func,
		}
	}
}
impl<'a> Function for CondFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		if is_truthy(try!(self.cond.call(scope))) {
			self.func.call(scope)
		} else {
			Ok(0_f32)
		}
	}
}

// A SumFunction represents the sum of a bunch of other functions. Functions defined in syntizer
// are internally represented as this.
struct SumFunction<'a> {
	sum: &'a Sum<'a>
}
impl<'a> SumFunction<'a> {
	pub fn new(sum: &'a Sum<'a>) -> SumFunction<'a> {
		SumFunction {
			sum: sum,
		}
	}
}
impl<'a> Function for SumFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		self.sum.eval(scope)
	}
}

#[test]
fn const_function_test() {
	let f = ConstFunction::new(42_f32);
	assert!(f.call(&Scope::new()).unwrap() == 42_f32);
}

#[test]
fn expr_function_test() {
	let mut s = Scope::new();
	s.define_var("a", 9_f32);
	let e = Expression::new(lexer::tokenize("5*3+a").unwrap().as_slice(), &s).unwrap();
	let f = ExprFunction::new(&e);
	assert!(f.call(&s).unwrap() == 24_f32);
}

#[test]
fn sin_test() {
	let a = 2_f32;
	let mut s = Scope::new();
	s.define_var("a", a);
	let f = SinFunction::new();
	assert!(f.call(&s).unwrap() == a.sin());
}

#[test]
fn cond_test() {
	let cond_truthy = ConstFunction::new(TRUE);
	let cond_falsey = ConstFunction::new(FALSE);
	let expr = ConstFunction::new(42_f32);
	let f_truthy = CondFunction::new(box cond_truthy, box expr);
	let f_falsey = CondFunction::new(box cond_falsey, box expr);
	let s = Scope::new();
	assert!(f_truthy.call(&s).unwrap() == 42_f32);
	assert!(f_falsey.call(&s).unwrap() == 0_f32);
}

#[test]
fn sum_test() {
	let sum = Sum::new(vec![
		box ConstFunction::new(1_f32) as Box<Function>,
		box ConstFunction::new(2_f32) as Box<Function>,
		box ConstFunction::new(3_f32) as Box<Function>,
		box ConstFunction::new(4_f32) as Box<Function>]);
	let f = SumFunction::new(&sum);
	let s = Scope::new();
	assert!(f.call(&s).unwrap() == 10_f32);
}
<commit_msg>fix some copypasta spaces -> tabs<commit_after>use super::expr::Expression;
use super::{CompileError, is_truthy};
use super::scope::Scope;
use super::sum::Sum;

#[cfg(test)]
use super::lexer;
#[cfg(test)]
use super::{TRUE, FALSE};

// Something that can be called with arguments given in the scope
pub trait Function {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError>;
}

macro_rules! bind_function(
	( $name:ident, $func:ident ( $($arg:ident),* ) ) => (
		struct $name;
		impl $name {
			fn new() -> $name {
				$name
			}
		}
		impl Function for $name {
			#[allow(unused_variables)] // Compiler complains that scope is not used on functions with no args.
			fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
				Ok($func($(
					// Insert each argument from the scope
					match scope.var_id(stringify!($arg)) {
						Some(id) => scope.get_var(id).unwrap(),

						None => return Err(CompileError {
							msg: format!("function `{}` requires argument `{}` but it is not defined in scope", stringify!($func), stringify!($arg)),
							pos: None }),
					}
				),*))
			}
		}
	);
)

fn sin(a: f32) -> f32 {
	a.sin()
}

bind_function!(SinFunction, sin(a))

// Always returns a specific constant
struct ConstFunction {
	val: f32,
}
impl ConstFunction {
	fn new(val: f32) -> ConstFunction {
		ConstFunction {
			val: val,
		}
	}
}
impl Function for ConstFunction {
	fn call(&self, _: &Scope) -> Result<f32, CompileError> {
		Ok(self.val)
	}
}

// Wraps an expression from the expr module.
struct ExprFunction<'a> {
	expr: &'a Expression<'a>,
}
impl<'a> ExprFunction<'a> {
	fn new(expr: &'a Expression<'a>) -> ExprFunction<'a> {
		ExprFunction {
			expr: expr,
		}
	}
}
impl<'a> Function for ExprFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		self.expr.eval(scope)
	}
}

// Returns the result of calling the function if the condition is truthy, else 0
struct CondFunction<'a> {
	cond: Box<Function + 'a>,
	func: Box<Function + 'a>,
}
impl<'a> CondFunction<'a> {
	fn new(cond: Box<Function + 'a>, func: Box<Function + 'a>) -> CondFunction<'a> {
		CondFunction {
			cond: cond,
			func: func,
		}
	}
}
impl<'a> Function for CondFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		if is_truthy(try!(self.cond.call(scope))) {
			self.func.call(scope)
		} else {
			Ok(0_f32)
		}
	}
}

// A SumFunction represents the sum of a bunch of other functions. Functions defined in syntizer
// are internally represented as this.
struct SumFunction<'a> {
	sum: &'a Sum<'a>
}
impl<'a> SumFunction<'a> {
	pub fn new(sum: &'a Sum<'a>) -> SumFunction<'a> {
		SumFunction {
			sum: sum,
		}
	}
}
impl<'a> Function for SumFunction<'a> {
	fn call(&self, scope: &Scope) -> Result<f32, CompileError> {
		self.sum.eval(scope)
	}
}

#[test]
fn const_function_test() {
	let f = ConstFunction::new(42_f32);
	assert!(f.call(&Scope::new()).unwrap() == 42_f32);
}

#[test]
fn expr_function_test() {
	let mut s = Scope::new();
	s.define_var("a", 9_f32);
	let e = Expression::new(lexer::tokenize("5*3+a").unwrap().as_slice(), &s).unwrap();
	let f = ExprFunction::new(&e);
	assert!(f.call(&s).unwrap() == 24_f32);
}

#[test]
fn sin_test() {
	let a = 2_f32;
	let mut s = Scope::new();
	s.define_var("a", a);
	let f = SinFunction::new();
	assert!(f.call(&s).unwrap() == a.sin());
}

#[test]
fn cond_test() {
	let cond_truthy = ConstFunction::new(TRUE);
	let cond_falsey = ConstFunction::new(FALSE);
	let expr = ConstFunction::new(42_f32);
	let f_truthy = CondFunction::new(box cond_truthy, box expr);
	let f_falsey = CondFunction::new(box cond_falsey, box expr);
	let s = Scope::new();
	assert!(f_truthy.call(&s).unwrap() == 42_f32);
	assert!(f_falsey.call(&s).unwrap() == 0_f32);
}

#[test]
fn sum_test() {
	let sum = Sum::new(vec![
		box ConstFunction::new(1_f32) as Box<Function>,
		box ConstFunction::new(2_f32) as Box<Function>,
		box ConstFunction::new(3_f32) as Box<Function>,
		box ConstFunction::new(4_f32) as Box<Function>]);
	let f = SumFunction::new(&sum);
	let s = Scope::new();
	assert!(f.call(&s).unwrap() == 10_f32);
}
<|endoftext|>