<commit_before>use url::form_urlencoded;
use command::{Command, Query};
use command::Command::Dump;

#[derive(Clone, Debug)]
pub struct CommandQuery {
    command: Command,
    arguments: Query,
    prefix: String,
}

impl Default for CommandQuery {
    fn default() -> CommandQuery {
        CommandQuery {
            command: Dump,
            arguments: vec![],
            prefix: "/d".to_string(),
        }
    }
}

impl CommandQuery {
    pub fn new(command: Command, query: Query) -> CommandQuery {
        let default: CommandQuery = Default::default();
        CommandQuery {
            command: command,
            arguments: query,
            prefix: default.prefix,
        }
    }

    /// Get vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    #[doc(hidden)]
    // get HTTP URI prefix. default: /d
    // This function is mainly provided for internal usage.
    pub fn get_prefix(&mut self) -> String {
        self.prefix.clone()
    }

    #[doc(hidden)]
    // set HTTP URI prefix. This function is provided for advanced user.
    pub fn set_prefix(&mut self, prefix: String) {
        self.prefix = prefix
    }

    /// Create url encoded command query.
    ///
    /// `vec![("key","value")]` interprets to `"key=value"`.
    /// And two or more value pair are concatinate with `&`.
    pub fn make_query(&mut self) -> String {
        form_urlencoded::serialize(self.arguments.clone().into_iter())
    }

    ///
    /// Create Groonga HTTP server query URL.
    pub fn encode(&mut self) -> String {
        format!("{}/{}?{}",
                self.get_prefix(),
                self.get_command(),
                self.make_query())
    }
}

#[cfg(test)]
mod test {
    use super::CommandQuery;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
                                   .filter("output_column @ \"type_safe\"".to_string())
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("test".to_string(), load_data.to_string())
                                           .input_type(InputType::Json)
                                           .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/load?table=test&input_type=json";
        assert_eq!(url_encoded.to_string(), command.encode());
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/status?";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
                                   .tables(vec!["Books".to_string(), "Categories".to_string()])
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/dump?tables=Books%2CCategories";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
                                   .filter("author == unknown".to_string())
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/delete?table=Books&filter=%27author+%3D%3D+unknown%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
                                   .flags(vec![(TableFlagType::PatKey),
                                               (TableFlagType::KeyWithSIS)])
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/table_create?name=Test&flags=TABLE_PAT_KEY%7CTABLE_KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
                                   .column_type(DataType::LongText)
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/column_create?table=Test&name=element&type=LongText";
        assert_eq!(url_encoded.to_string(), command.encode());
    }
}
<commit_msg>command_query: Fix inconsitent methods<commit_after>use url::form_urlencoded;
use command::{Command, Query};
use command::Command::Dump;

#[derive(Clone, Debug)]
pub struct CommandQuery {
    command: Command,
    arguments: Query,
    prefix: String,
}

impl Default for CommandQuery {
    fn default() -> CommandQuery {
        CommandQuery {
            command: Dump,
            arguments: vec![],
            prefix: "/d".to_string(),
        }
    }
}

impl CommandQuery {
    pub fn new(command: Command, query: Query) -> CommandQuery {
        let default: CommandQuery = Default::default();
        CommandQuery {
            command: command,
            arguments: query,
            prefix: default.prefix,
        }
    }

    /// Get command enum constant to construct url encoded query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    #[doc(hidden)]
    // get HTTP URI prefix. default: /d
    // This function is mainly provided for internal usage.
    pub fn get_prefix(&mut self) -> String {
        self.prefix.clone()
    }

    #[doc(hidden)]
    // set HTTP URI prefix. This function is provided for advanced user.
    pub fn set_prefix(&mut self, prefix: String) {
        self.prefix = prefix
    }

    /// Create url encoded command query.
    ///
    /// `vec![("key","value")]` interprets to `"key=value"`.
    /// And two or more value pair are concatinate with `&`.
    pub fn make_query(&mut self) -> String {
        form_urlencoded::serialize(self.arguments.clone().into_iter())
    }

    ///
    /// Create Groonga HTTP server query URL.
    pub fn encode(&mut self) -> String {
        format!("{}/{}?{}",
                self.get_prefix(),
                self.get_command(),
                self.make_query())
    }
}

#[cfg(test)]
mod test {
    use super::CommandQuery;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
                                   .filter("output_column @ \"type_safe\"".to_string())
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("test".to_string(), load_data.to_string())
                                           .input_type(InputType::Json)
                                           .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/load?table=test&input_type=json";
        assert_eq!(url_encoded.to_string(), command.encode());
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/status?";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
                                   .tables(vec!["Books".to_string(), "Categories".to_string()])
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/dump?tables=Books%2CCategories";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
                                   .filter("author == unknown".to_string())
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/delete?table=Books&filter=%27author+%3D%3D+unknown%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
                                   .flags(vec![(TableFlagType::PatKey),
                                               (TableFlagType::KeyWithSIS)])
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/table_create?name=Test&flags=TABLE_PAT_KEY%7CTABLE_KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
                                   .column_type(DataType::LongText)
                                   .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/column_create?table=Test&name=element&type=LongText";
        assert_eq!(url_encoded.to_string(), command.encode());
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;
extern crate plank_x86_backend;

mod ast_printer;

use std::convert::From;
use std::io;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use plank_errors::Reporter;

#[derive(Debug)]
enum Error {
    Io(io::Error),
    BuildFail,
    Interpreter(plank_interpreter::Error),
    InterpreterExit(i32),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<plank_interpreter::Error> for Error {
    fn from(err: plank_interpreter::Error) -> Error {
        Error::Interpreter(err)
    }
}

#[derive(Debug)]
enum Command {
    Lex,
    Parse,
    EmitIr,
    Interpret,
    CompileX86,
}

#[derive(Debug)]
enum Stream {
    File(PathBuf),
    Std,
}

#[derive(Debug)]
struct Params {
    command: Command,
    optimize: bool,
    skip_prelude: bool,
    input: Stream,
    output: Stream,
}

type Result<T> = ::std::result::Result<T, Error>;

fn main() {
    match run() {
        Ok(()) => {}
        Err(Error::BuildFail) => {
            eprintln!("error: build failed");
            ::std::process::exit(1);
        }
        Err(Error::Io(err)) => {
            eprintln!("IO error:\n{}", err);
            ::std::process::exit(1);
        }
        Err(Error::Interpreter(ref err)) => {
            eprintln!("Interpreter failed:\n{}", err);
            ::std::process::exit(1);
        }
        Err(Error::InterpreterExit(code)) => {
            eprintln!("Interpreter exited with status code {}", code);
            ::std::process::exit(code);
        }
    }
}

fn run() -> Result<()> {
    let params = parse_params()?;
    let input = read_input(&params.input)?;
    match params.output {
        Stream::Std => {
            let stdout = io::stdout();
            let stdout = stdout.lock();
            run_command(&input, &params.command, params.optimize, params.skip_prelude, stdout)
        }
        Stream::File(ref name) => {
            let file = ::std::fs::File::create(name)?;
            run_command(&input, &params.command, params.optimize, params.skip_prelude, file)
        }
    }
}

fn run_command<W: Write>(input: &str, command: &Command, optimize: bool, skip_prelude: bool, output: W) -> Result<()> {
    match *command {
        Command::Lex => lex(input, output),
        Command::Parse => parse(input, output),
        Command::EmitIr => emit_ir(input, output, optimize),
        Command::Interpret => interpret(input, output, optimize),
        Command::CompileX86 => compile_x86(input, output, optimize, skip_prelude),
    }
}

fn parse_params() -> Result<Params> {
    use clap::{App, Arg};

    let matches = App::new("Plank compiler")
        .arg(Arg::with_name("lex")
            .long("lex")
            .help("List tokens in input")
            .conflicts_with_all(&["parse", "emit-ir", "interpret", "emit-asm"]))
        .arg(Arg::with_name("parse")
            .long("parse")
            .help("Parse input")
            .conflicts_with_all(&["lex", "emit-ir", "interpret", "emit-asm"]))
        .arg(Arg::with_name("emit-ir")
            .long("emit-ir")
            .help("Compile to plank IR")
            .conflicts_with_all(&["lex", "parse", "interpret", "emit-asm"]))
        .arg(Arg::with_name("interpret")
            .long("interpret")
            .help("Compile to IR and interpret")
            .conflicts_with_all(&["lex", "parse", "emit-ir", "emit-asm"]))
        .arg(Arg::with_name("emit-asm")
            .long("emit-asm")
            .help("Compile to x86 assembly")
            .conflicts_with_all(&["lex", "parse", "emit-ir", "interpret"]))
        .arg(Arg::with_name("optimize")
            .long("optimize")
            .short("O")
            .help("Perform optimizations on IR"))
        .arg(Arg::with_name("no-prelude")
            .long("no-prelude")
            .help("Don't emit asm prelude"))
        .arg(Arg::with_name("input")
            .index(1)
            .help("Set input file, uses stdin if none provided"))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .takes_value(true)
            .help("Set output file, uses stdout if none provided"))
        .get_matches();
    let default_command = Command::Interpret;
    let command = if matches.is_present("lex") {
        Command::Lex
    } else if matches.is_present("parse") {
        Command::Parse
    } else if matches.is_present("emit-ir") {
        Command::EmitIr
    } else if matches.is_present("interpret") {
        Command::Interpret
    } else if matches.is_present("emit-asm") {
        Command::CompileX86
    } else {
        default_command
    };

    let input = match matches.value_of_os("input") {
        Some(path) => Stream::File(Path::new(path).to_owned()),
        None => Stream::Std,
    };

    let output = match matches.value_of_os("output") {
        Some(path) => Stream::File(Path::new(path).to_owned()),
        None => Stream::Std,
    };

    let optimize = matches.is_present("optimize");
    let skip_prelude = matches.is_present("no-prelude");

    Ok(Params {
        command,
        optimize,
        skip_prelude,
        input,
        output,
    })
}

fn read_file(name: &Path) -> Result<String> {
    use std::fs::File;
    let mut file = File::open(name)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

fn read_stdin() -> Result<String> {
    use std::io::prelude::*;
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut input = String::new();
    stdin.read_to_string(&mut input)?;
    Ok(input)
}

fn read_input(stream: &Stream) -> Result<String> {
    match *stream {
        Stream::File(ref file) => read_file(file),
        Stream::Std => read_stdin(),
    }
}

fn emit_diagnostics(input: &str, reporter: Reporter) -> Result<()> {
    let mut diagnostics = reporter.get_diagnostics();
    diagnostics.sort_by_key(|d| d.primary_span.map(|s| s.start));
    plank_errors::print_diagnostics(&input, &diagnostics);
    if reporter.has_errors() {
        Err(Error::BuildFail)
    } else {
        Ok(())
    }
}

fn lex<W: Write>(source: &str, mut output: W) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    emit_diagnostics(source, reporter)?;
    for tok in tokens {
        output.write_fmt(format_args!("{:?}\n", *tok))?;
    }
    Ok(())
}

fn parse<W: Write>(source: &str, mut output: W) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let formatted = ast_printer::format_program(&program);
    output.write_all(formatted.as_bytes())?;
    output.write_all(b"\n")?;
    Ok(())
}

fn emit_ir<W: Write>(source: &str, mut output: W, optimize: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("no errors but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    plank_ir::emit_program(&ir, &mut output)?;
    if let Err((sym, err)) = plank_ir::validate_ir(&ir) {
        eprintln!("ir validation error in function {:?}: {:?}", sym, err);
    }
    Ok(())
}

fn interpret<W: Write>(source: &str, output: W, optimize: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("build succeeded but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    let input = io::empty();
    let exit_code = plank_interpreter::run_program(&ir, input, output)?;
    if exit_code == 0 {
        Ok(())
    } else {
        Err(Error::InterpreterExit(exit_code))
    }
}

fn compile_x86<W: Write>(source: &str, mut output: W, optimize: bool, skip_prelude: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("build succeeded but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    plank_x86_backend::fix_function_returns(&mut ir);
    let asm = plank_x86_backend::compile_program(&ir);
    if !skip_prelude {
        plank_x86_backend::print_prelude(&mut output)?;
    }
    plank_x86_backend::print_asm(output, &asm)?;
    Ok(())
}
<commit_msg>allow interpreter to read stdin if source was from file<commit_after>extern crate clap;
extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;
extern crate plank_x86_backend;

mod ast_printer;

use std::convert::From;
use std::io;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use plank_errors::Reporter;

#[derive(Debug)]
enum Error {
    Io(io::Error),
    BuildFail,
    Interpreter(plank_interpreter::Error),
    InterpreterExit(i32),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<plank_interpreter::Error> for Error {
    fn from(err: plank_interpreter::Error) -> Error {
        Error::Interpreter(err)
    }
}

#[derive(Debug)]
enum Command {
    Lex,
    Parse,
    EmitIr,
    Interpret,
    CompileX86,
}

#[derive(Debug)]
enum Stream {
    File(PathBuf),
    Std,
}

impl Stream {
    fn is_std(&self) -> bool {
        match self {
            Stream::File(_) => false,
            Stream::Std => true,
        }
    }
}

#[derive(Debug)]
struct Params {
    command: Command,
    optimize: bool,
    skip_prelude: bool,
    input: Stream,
    output: Stream,
}

type Result<T> = ::std::result::Result<T, Error>;

fn main() {
    match run() {
        Ok(()) => {}
        Err(Error::BuildFail) => {
            eprintln!("error: build failed");
            ::std::process::exit(1);
        }
        Err(Error::Io(err)) => {
            eprintln!("IO error:\n{}", err);
            ::std::process::exit(1);
        }
        Err(Error::Interpreter(ref err)) => {
            eprintln!("Interpreter failed:\n{}", err);
            ::std::process::exit(1);
        }
        Err(Error::InterpreterExit(code)) => {
            eprintln!("Interpreter exited with status code {}", code);
            ::std::process::exit(code);
        }
    }
}

fn run() -> Result<()> {
    let params = parse_params()?;
    let input = read_input(&params.input)?;
    let can_read_stdin = !params.input.is_std();
    match params.output {
        Stream::Std => {
            let stdout = io::stdout();
            let stdout = stdout.lock();
            run_command(&input, &params.command, can_read_stdin, params.optimize, params.skip_prelude, stdout)
        }
        Stream::File(ref name) => {
            let file = ::std::fs::File::create(name)?;
            run_command(&input, &params.command, can_read_stdin, params.optimize, params.skip_prelude, file)
        }
    }
}

fn run_command<W: Write>(
    input: &str,
    command: &Command,
    can_read_stdin: bool,
    optimize: bool,
    skip_prelude: bool,
    output: W,
) -> Result<()> {
    match *command {
        Command::Lex => lex(input, output),
        Command::Parse => parse(input, output),
        Command::EmitIr => emit_ir(input, output, optimize),
        Command::Interpret => interpret(input, can_read_stdin, output, optimize),
        Command::CompileX86 => compile_x86(input, output, optimize, skip_prelude),
    }
}

fn parse_params() -> Result<Params> {
    use clap::{App, Arg};

    let matches = App::new("Plank compiler")
        .arg(Arg::with_name("lex")
            .long("lex")
            .help("List tokens in input")
            .conflicts_with_all(&["parse", "emit-ir", "interpret", "emit-asm"]))
        .arg(Arg::with_name("parse")
            .long("parse")
            .help("Parse input")
            .conflicts_with_all(&["lex", "emit-ir", "interpret", "emit-asm"]))
        .arg(Arg::with_name("emit-ir")
            .long("emit-ir")
            .help("Compile to plank IR")
            .conflicts_with_all(&["lex", "parse", "interpret", "emit-asm"]))
        .arg(Arg::with_name("interpret")
            .long("interpret")
            .help("Compile to IR and interpret")
            .conflicts_with_all(&["lex", "parse", "emit-ir", "emit-asm"]))
        .arg(Arg::with_name("emit-asm")
            .long("emit-asm")
            .help("Compile to x86 assembly")
            .conflicts_with_all(&["lex", "parse", "emit-ir", "interpret"]))
        .arg(Arg::with_name("optimize")
            .long("optimize")
            .short("O")
            .help("Perform optimizations on IR"))
        .arg(Arg::with_name("no-prelude")
            .long("no-prelude")
            .help("Don't emit asm prelude"))
        .arg(Arg::with_name("input")
            .index(1)
            .help("Set input file, uses stdin if none provided"))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .takes_value(true)
            .help("Set output file, uses stdout if none provided"))
        .get_matches();
    let default_command = Command::Interpret;
    let command = if matches.is_present("lex") {
        Command::Lex
    } else if matches.is_present("parse") {
        Command::Parse
    } else if matches.is_present("emit-ir") {
        Command::EmitIr
    } else if matches.is_present("interpret") {
        Command::Interpret
    } else if matches.is_present("emit-asm") {
        Command::CompileX86
    } else {
        default_command
    };

    let input = match matches.value_of_os("input") {
        Some(path) => Stream::File(Path::new(path).to_owned()),
        None => Stream::Std,
    };

    let output = match matches.value_of_os("output") {
        Some(path) => Stream::File(Path::new(path).to_owned()),
        None => Stream::Std,
    };

    let optimize = matches.is_present("optimize");
    let skip_prelude = matches.is_present("no-prelude");

    Ok(Params {
        command,
        optimize,
        skip_prelude,
        input,
        output,
    })
}

fn read_file(name: &Path) -> Result<String> {
    use std::fs::File;
    let mut file = File::open(name)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

fn read_stdin() -> Result<String> {
    use std::io::prelude::*;
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut input = String::new();
    stdin.read_to_string(&mut input)?;
    Ok(input)
}

fn read_input(stream: &Stream) -> Result<String> {
    match *stream {
        Stream::File(ref file) => read_file(file),
        Stream::Std => read_stdin(),
    }
}

fn emit_diagnostics(input: &str, reporter: Reporter) -> Result<()> {
    let mut diagnostics = reporter.get_diagnostics();
    diagnostics.sort_by_key(|d| d.primary_span.map(|s| s.start));
    plank_errors::print_diagnostics(&input, &diagnostics);
    if reporter.has_errors() {
        Err(Error::BuildFail)
    } else {
        Ok(())
    }
}

fn lex<W: Write>(source: &str, mut output: W) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    emit_diagnostics(source, reporter)?;
    for tok in tokens {
        output.write_fmt(format_args!("{:?}\n", *tok))?;
    }
    Ok(())
}

fn parse<W: Write>(source: &str, mut output: W) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let formatted = ast_printer::format_program(&program);
    output.write_all(formatted.as_bytes())?;
    output.write_all(b"\n")?;
    Ok(())
}

fn emit_ir<W: Write>(source: &str, mut output: W, optimize: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("no errors but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    plank_ir::emit_program(&ir, &mut output)?;
    if let Err((sym, err)) = plank_ir::validate_ir(&ir) {
        eprintln!("ir validation error in function {:?}: {:?}", sym, err);
    }
    Ok(())
}

fn interpret<W: Write>(source: &str, can_read_stdin: bool, output: W, optimize: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("build succeeded but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    let stdin;
    let mut stdin_lock;
    let mut empty = io::empty();
    let input: &mut dyn Read = if can_read_stdin {
        stdin = io::stdin();
        stdin_lock = stdin.lock();
        &mut stdin_lock
    } else {
        &mut empty
    };
    let exit_code = plank_interpreter::run_program(&ir, input, output)?;
    if exit_code == 0 {
        Ok(())
    } else {
        Err(Error::InterpreterExit(exit_code))
    }
}

fn compile_x86<W: Write>(source: &str, mut output: W, optimize: bool, skip_prelude: bool) -> Result<()> {
    let reporter = Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone());
    emit_diagnostics(source, reporter)?;
    let mut ir = ir.expect("build succeeded but failed to produce IR");
    if optimize {
        plank_ir::optimization::optimize(&mut ir);
    }
    plank_x86_backend::fix_function_returns(&mut ir);
    let asm = plank_x86_backend::compile_program(&ir);
    if !skip_prelude {
        plank_x86_backend::print_prelude(&mut output)?;
    }
    plank_x86_backend::print_asm(output, &asm)?;
    Ok(())
}
<|endoftext|>


<commit_before>extern crate minifb;
extern crate bgfx_rs;
extern crate viewdock;

use bgfx_rs::Bgfx;
use libc::{c_void, c_int};
use minifb::{Scale, WindowOptions, MouseMode, MouseButton};
use core::view_plugins::{ViewHandle, ViewPlugins, ViewInstance};
use core::session::{Sessions, Session, SessionHandle};
use self::viewdock::{Workspace, Rect, Direction, DockHandle};
use imgui_sys::Imgui;
use prodbg_api::ui_ffi::{PDVec2};
use prodbg_api::view::CViewCallbacks;

const WIDTH: usize = 1280;
const HEIGHT: usize = 800;

pub struct Window {
    /// minifb window
    pub win: minifb::Window,

    /// Views in this window
    pub views: Vec<ViewHandle>,

    ///
    pub ws: Workspace,
}

///! Windows keeps track of all different windows that are present with in the application
///! There are several ways windows can be created:
///!
///! 1. User opens a new window using a shortcut or menu selection.
///! 2. User "undocks" a view from an existing window giving it it's own floating window.
///! 3. etc

pub struct Windows {
    /// All the windows being tracked
    windows: Vec<Window>,
    current: usize,
}

impl Windows {
    pub fn new() -> Windows {
        Windows {
            windows: Vec::new(),
            current: 0,
        }
    }

    /// Create a default window which will only be created if there are no other
    pub fn create_default(&mut self) {
        if self.windows.len() > 0 {
            return;
        }

        let window = Self::create_window(WIDTH, HEIGHT).expect("Unable to create window");

        self.windows.push(window)
   }

    pub fn create_window(width: usize, height: usize) -> minifb::Result<Window> {
        let res = minifb::Window::new("ProDBG",
                                      width,
                                      height,
                                      WindowOptions {
                                          resize: true,
                                          scale: Scale::X1,
                                          ..WindowOptions::default()
                                      });
        match res {
            Ok(win) => {
                Bgfx::create_window(win.get_window_handle() as *const c_void,
                                    width as c_int,
                                    height as c_int);
                Ok(Window {
                    win: win,
                    views: Vec::new(),
                    ws: Workspace::new(Rect::new(0.0, 0.0, width as f32, height as f32)).unwrap(),
                })
            }
            Err(err) => Err(err),
        }
    }

    pub fn create_window_with_menus(&mut self) -> minifb::Result<Window> {
        //const WIDTH: usize = 1280;
        //const HEIGHT: usize = 1024;

        let window = try!(Self::create_window(WIDTH, HEIGHT));

        // for menu in &menus {
        // window.add_menu(m.name, m.menu);
        // }
        //

        Ok(window)
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        for i in (0..self.windows.len()).rev() {
            self.windows[i].update(sessions, view_plugins);

            if !self.windows[i].win.is_open() {
                self.windows.swap_remove(i);
            }
        }
    }

    pub fn get_current(&mut self) -> &mut Window {
        let current = self.current;
        &mut self.windows[current]
    }

    /// Checks if application should exit (all window instances closed)
    pub fn should_exit(&self) -> bool {
        self.windows.len() == 0
    }

    /// Save the state of the windows (usually done when exiting the application)
    pub fn save(_filename: &str) {}

    /// Load the state of all the views from a previous run
    pub fn load(_filename: &str) {}
}

impl Window {
    fn is_inside(v: (f32, f32), pos: PDVec2, size: PDVec2) -> bool {
        let x0 = pos.x;
        let y0 = pos.y;
        let x1 = pos.x + size.x;
        let y1 = pos.y + size.y;

        if (v.0 >= x0 && v.0 < x1) && (v.1 >= y0 && v.1 < y1) {
            true
        } else {
            false
        }
    }

    fn update_view(&self, instance: &mut ViewInstance, session: &mut Session, show_context_menu: bool, mouse: (f32, f32)) -> u32 {
        let ui = instance.ui;

        if let Some(rect) = self.ws.get_rect_by_handle(DockHandle(instance.handle.0)) {
            Imgui::set_window_pos(rect.x, rect.y);
            Imgui::set_window_size(rect.width, rect.height);
        }

        Imgui::begin_window(&instance.name, true);
        Imgui::init_state(ui.api);

        let pos = ui.get_window_pos();
        let size = ui.get_window_size();

        if Self::is_inside(mouse, pos, size) && show_context_menu {
            Imgui::mark_show_popup(ui.api, true);
        } else {
            Imgui::mark_show_popup(ui.api, false);
        }

        unsafe {
            let plugin_funcs = instance.plugin_type.plugin_funcs as *mut CViewCallbacks;
            ((*plugin_funcs).update.unwrap())(instance.plugin_data,
                                                ui.api as *mut c_void,
                                                session.reader.api as *mut c_void,
                                                session.get_current_writer().api as *mut c_void);
        }

        let has_shown_menu = Imgui::has_showed_popup(ui.api);

        Imgui::end_window();

        has_shown_menu
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        self.win.update();

        let mut has_shown_menu = 0u32;

        self.ws.update();

        let mouse = self.win.get_mouse_pos(MouseMode::Clamp).unwrap_or((0.0, 0.0));

        Bgfx::set_mouse_pos(mouse);
        Bgfx::set_mouse_state(0, self.win.get_mouse_down(MouseButton::Left));

        let show_context_menu = self.win.get_mouse_down(MouseButton::Right);

        for view in &self.views {
            if let Some(ref mut v) = view_plugins.get_view(*view) {
                if let Some(ref mut s) = sessions.get_session(v.session_handle) {
                    has_shown_menu |= Self::update_view(self, v, s, show_context_menu, mouse);
                }
            }
        }

        // if now plugin has showed a menu we do it here
        // TODO: Handle diffrent cases when attach menu on to plugin menu or not

        if has_shown_menu == 0 && show_context_menu {
            Self::show_popup(self, true, mouse, view_plugins);
        } else {
            Self::show_popup(self, false, mouse, view_plugins);
        }
    }

    /*
    fn add_view(&mut self, name: &String, view_plugins: &mut ViewPlugins) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            self.views.push(handle);
        }
    }
    */

    fn split_view(&mut self, name: &String, view_plugins: &mut ViewPlugins, pos: (f32, f32), direction: Direction) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            if let Some(dock_handle) = self.ws.is_hovering_dock(pos) {
                self.ws.split_by_dock_handle(direction, dock_handle, DockHandle(handle.0));
            } else {
                self.ws.split_top(DockHandle(handle.0), direction);
            }

            self.views.push(handle);
        }
    }

    fn show_popup(&mut self, show: bool, mouse_pos: (f32, f32), view_plugins: &mut ViewPlugins) {
        let ui = Imgui::get_ui();

        if show {
            ui.open_popup("plugins");
        }

        if ui.begin_popup("plugins") {
            let plugin_names = view_plugins.get_plugin_names();

            if ui.begin_menu("Split Horizontally", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Horizontal);
                    }
                }
                ui.end_menu();
            }

            if ui.begin_menu("Split Vertically", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Vertical);
                    }
                }
                ui.end_menu();
            }

            ui.end_popup();
        }
    }
}
<commit_msg>Fixed border + some debug info<commit_after>extern crate minifb;
extern crate bgfx_rs;
extern crate viewdock;

use bgfx_rs::Bgfx;
use libc::{c_void, c_int};
use minifb::{Scale, WindowOptions, MouseMode, MouseButton};
use core::view_plugins::{ViewHandle, ViewPlugins, ViewInstance};
use core::session::{Sessions, Session, SessionHandle};
use self::viewdock::{Workspace, Rect, Direction, DockHandle};
use imgui_sys::Imgui;
use prodbg_api::ui_ffi::{PDVec2};
use prodbg_api::view::CViewCallbacks;

const WIDTH: usize = 1280;
const HEIGHT: usize = 800;

pub struct Window {
    /// minifb window
    pub win: minifb::Window,

    /// Views in this window
    pub views: Vec<ViewHandle>,

    ///
    pub ws: Workspace,
}

///! Windows keeps track of all different windows that are present with in the application
///! There are several ways windows can be created:
///!
///! 1. User opens a new window using a shortcut or menu selection.
///! 2. User "undocks" a view from an existing window giving it it's own floating window.
///! 3. etc

pub struct Windows {
    /// All the windows being tracked
    windows: Vec<Window>,
    current: usize,
}

impl Windows {
    pub fn new() -> Windows {
        Windows {
            windows: Vec::new(),
            current: 0,
        }
    }

    /// Create a default window which will only be created if there are no other
    pub fn create_default(&mut self) {
        if self.windows.len() > 0 {
            return;
        }

        let window = Self::create_window(WIDTH, HEIGHT).expect("Unable to create window");

        self.windows.push(window)
   }

    pub fn create_window(width: usize, height: usize) -> minifb::Result<Window> {
        let res = minifb::Window::new("ProDBG",
                                      width,
                                      height,
                                      WindowOptions {
                                          resize: true,
                                          scale: Scale::X1,
                                          ..WindowOptions::default()
                                      });
        match res {
            Ok(win) => {
                Bgfx::create_window(win.get_window_handle() as *const c_void,
                                    width as c_int,
                                    height as c_int);
                Ok(Window {
                    win: win,
                    views: Vec::new(),
                    ws: Workspace::new(Rect::new(0.0, 0.0, width as f32, (height - 20) as f32)).unwrap(),
                })
            }
            Err(err) => Err(err),
        }
    }

    pub fn create_window_with_menus(&mut self) -> minifb::Result<Window> {
        //const WIDTH: usize = 1280;
        //const HEIGHT: usize = 1024;

        let window = try!(Self::create_window(WIDTH, HEIGHT));

        // for menu in &menus {
        // window.add_menu(m.name, m.menu);
        // }
        //

        Ok(window)
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        for i in (0..self.windows.len()).rev() {
            self.windows[i].update(sessions, view_plugins);

            if !self.windows[i].win.is_open() {
                self.windows.swap_remove(i);
            }
        }
    }

    pub fn get_current(&mut self) -> &mut Window {
        let current = self.current;
        &mut self.windows[current]
    }

    /// Checks if application should exit (all window instances closed)
    pub fn should_exit(&self) -> bool {
        self.windows.len() == 0
    }

    /// Save the state of the windows (usually done when exiting the application)
    pub fn save(_filename: &str) {}

    /// Load the state of all the views from a previous run
    pub fn load(_filename: &str) {}
}

impl Window {
    fn is_inside(v: (f32, f32), pos: PDVec2, size: PDVec2) -> bool {
        let x0 = pos.x;
        let y0 = pos.y;
        let x1 = pos.x + size.x;
        let y1 = pos.y + size.y;

        if (v.0 >= x0 && v.0 < x1) && (v.1 >= y0 && v.1 < y1) {
            true
        } else {
            false
        }
    }

    fn update_view(&self, instance: &mut ViewInstance, session: &mut Session, show_context_menu: bool, mouse: (f32, f32)) -> u32 {
        let ui = instance.ui;

        if let Some(rect) = self.ws.get_rect_by_handle(DockHandle(instance.handle.0)) {
            Imgui::set_window_pos(rect.x, rect.y);
            Imgui::set_window_size(rect.width, rect.height);
        }

        Imgui::begin_window(&instance.name, true);
        Imgui::init_state(ui.api);

        let pos = ui.get_window_pos();
        let size = ui.get_window_size();

        if Self::is_inside(mouse, pos, size) && show_context_menu {
            Imgui::mark_show_popup(ui.api, true);
        } else {
            Imgui::mark_show_popup(ui.api, false);
        }

        unsafe {
            let plugin_funcs = instance.plugin_type.plugin_funcs as *mut CViewCallbacks;
            ((*plugin_funcs).update.unwrap())(instance.plugin_data,
                                                ui.api as *mut c_void,
                                                session.reader.api as *mut c_void,
                                                session.get_current_writer().api as *mut c_void);
        }

        let has_shown_menu = Imgui::has_showed_popup(ui.api);

        Imgui::end_window();

        has_shown_menu
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        self.win.update();

        let mut has_shown_menu = 0u32;

        self.ws.update();

        let mouse = self.win.get_mouse_pos(MouseMode::Clamp).unwrap_or((0.0, 0.0));

        Bgfx::set_mouse_pos(mouse);
        Bgfx::set_mouse_state(0, self.win.get_mouse_down(MouseButton::Left));

        let show_context_menu = self.win.get_mouse_down(MouseButton::Right);

        for view in &self.views {
            if let Some(ref mut v) = view_plugins.get_view(*view) {
                if let Some(ref mut s) = sessions.get_session(v.session_handle) {
                    has_shown_menu |= Self::update_view(self, v, s, show_context_menu, mouse);
                }
            }
        }

        // if now plugin has showed a menu we do it here
        // TODO: Handle diffrent cases when attach menu on to plugin menu or not

        if has_shown_menu == 0 && show_context_menu {
            Self::show_popup(self, true, mouse, view_plugins);
        } else {
            Self::show_popup(self, false, mouse, view_plugins);
        }
    }

    /*
    fn add_view(&mut self, name: &String, view_plugins: &mut ViewPlugins) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            self.views.push(handle);
        }
    }
    */

    fn split_view(&mut self, name: &String, view_plugins: &mut ViewPlugins, pos: (f32, f32), direction: Direction) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            if let Some(dock_handle) = self.ws.is_hovering_dock(pos) {
                println!("split_by_handle dock_handle {}", dock_handle.0);
                self.ws.split_by_dock_handle(direction, dock_handle, DockHandle(handle.0));
            } else {
                println!("split_top");
                self.ws.split_top(DockHandle(handle.0), direction);
            }

            self.views.push(handle);
        }
    }

    fn show_popup(&mut self, show: bool, mouse_pos: (f32, f32), view_plugins: &mut ViewPlugins) {
        let ui = Imgui::get_ui();

        if show {
            ui.open_popup("plugins");
        }

        if ui.begin_popup("plugins") {
            let plugin_names = view_plugins.get_plugin_names();

            if ui.begin_menu("Split Horizontally", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Horizontal);
                    }
                }
                ui.end_menu();
            }

            if ui.begin_menu("Split Vertically", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Vertical);
                    }
                }
                ui.end_menu();
            }

            ui.end_popup();
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use Construct;
use Of;
use ToPos;
use Count;
use Data;
use ToIndex;
use Zero;

/// Dimension is natural number, position is a list of numbers.
pub struct PowerSet<T = Data>(PhantomData<T>);

impl<T> Construct for PowerSet<T> {
    fn new() -> PowerSet<T> { PowerSet(PhantomData) }
}

impl Count<usize> for PowerSet<Data> {
    type N = usize;
    fn count(&self, dim: &usize) -> usize {
        1 << *dim
    }
}

impl<T, U> Count<U> for PowerSet<Of<T>>
    where
        T: Construct + Count<U, N = usize>
{
    type N = usize;
    fn count(&self, dim: &U) -> usize {
        let of: T = Construct::new();
        1 << of.count(dim)
    }
}

impl Zero<usize, Vec<usize>> for PowerSet<Data> {
    fn zero(&self, _dim: &usize) -> Vec<usize> {
        vec![]
    }
}

impl<T, U, V> Zero<U, Vec<V>> for PowerSet<Of<T>>
    where T: Construct + Count<U> + Zero<U, V>
{
    fn zero(&self, _dim: &U) -> Vec<V> {
        vec![]
    }
}

impl ToIndex<usize, Vec<usize>> for PowerSet<Data> {
    fn to_index(
        &self,
        _dim: &usize,
        pos: &Vec<usize>
    ) -> usize {
        let mut index = 0;
        for &i in pos.iter() {
            index |= 1 << i;
        }
        index
    }
}

impl<T, U, V>
ToIndex<U, Vec<V>> for PowerSet<Of<T>>
    where
        T: Construct + ToIndex<U, V>,
        V: Clone
{
    fn to_index(
        &self,
        dim: &U,
        pos: &Vec<V>
    ) -> usize {
        let of: T = Construct::new();
        let mut index = 0;
        for i in pos.iter() {
            index |= 1 << of.to_index(dim, i);
        }
        index
    }
}

impl ToPos<usize, Vec<usize>> for PowerSet<Data> {
    fn to_pos(
        &self,
        dim: &usize,
        index: usize,
        pos: &mut Vec<usize>
    ) {
        unsafe { pos.set_len(0); }
        for i in 0..*dim {
            if ((index >> i) & 1) == 1 {
                pos.push(i);
            }
        }
    }
}

impl<T, U, V>
ToPos<U, Vec<V>>
for PowerSet<Of<T>>
    where T: Construct + Count<U, N = usize> + ToPos<U, V> + Zero<U, V>
{
    fn to_pos(
        &self,
        dim: &U,
        index: usize,
        pos: &mut Vec<V>
    ) {
        let of: T = Construct::new();
        let count = of.count(dim);
        pos.clear();
        pos.reserve_exact(count);
        for j in 0..count {
            if ((index >> j) & 1) == 1 {
                let mut p = of.zero(dim);
                of.to_pos(dim, j, &mut p);
                pos.push(p);
            }
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<PowerSet, usize, Vec<usize>>();
        is_complete::<PowerSet<Of<Pair>>, usize, Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let x: PowerSet = Construct::new();
        let ref dim = 6;
        assert_eq!(x.count(dim), 64);
        assert_eq!(x.to_index(dim, &vec![]), 0);
        assert_eq!(x.to_index(dim, &vec![0]), 1);
        assert_eq!(x.to_index(dim, &vec![1]), 2);
        assert_eq!(x.to_index(dim, &vec![0, 1]), 3);
        let mut a = vec![];
        x.to_pos(dim, 9, &mut a);
        assert_eq!(&a, &[0, 3]);
    }

    #[test]
    fn of() {
        let x: PowerSet<Of<Pair>> = Construct::new();
        let ref dim = 4;
        assert_eq!(x.count(dim), 64);
        assert_eq!(x.to_index(dim, &vec![]), 0);
        assert_eq!(x.to_index(dim, &vec![(0, 1)]), 1);
        assert_eq!(x.to_index(dim, &vec![(0, 2)]), 2);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2)]), 3);
        assert_eq!(x.to_index(dim, &vec![(1, 2)]), 4);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (1, 2)]), 5);
        assert_eq!(x.to_index(dim, &vec![(0, 2), (1, 2)]), 6);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2), (1, 2)]), 7);
        let mut a = vec![(0, 0); 64];
        x.to_pos(dim, 7, &mut a);
        assert_eq!(a[0], (0, 1));
    }
}
<commit_msg>Impl `Count<BigUint>` for `PowerSet`<commit_after>use std::marker::PhantomData;

use num::BigUint;
use num::pow::Pow;

use Construct;
use Of;
use ToPos;
use Count;
use Data;
use ToIndex;
use Zero;

/// Dimension is natural number, position is a list of numbers.
pub struct PowerSet<T = Data>(PhantomData<T>);

impl<T> Construct for PowerSet<T> {
    fn new() -> PowerSet<T> { PowerSet(PhantomData) }
}

impl Count<usize> for PowerSet<Data> {
    type N = usize;
    fn count(&self, dim: &usize) -> usize {
        1 << *dim
    }
}

impl Count<BigUint> for PowerSet<Data> {
    type N = BigUint;
    fn count(&self, dim: &BigUint) -> BigUint {
        use std::convert::TryInto;

        let _two: BigUint = 2usize.into();
        let dim: u32 = dim.try_into().unwrap();
        _two.pow(dim)
    }
}

impl<T, U> Count<U> for PowerSet<Of<T>>
    where
        T: Construct + Count<U>,
        <T as Count<U>>::N: From<usize> + Pow<<T as Count<U>>::N, Output = <T as Count<U>>::N>,
{
    type N = <T as Count<U>>::N;
    fn count(&self, dim: &U) -> Self::N {
        let _two: Self::N = 2usize.into();
        let of: T = Construct::new();
        _two.pow(of.count(dim))
    }
}

impl Zero<usize, Vec<usize>> for PowerSet<Data> {
    fn zero(&self, _dim: &usize) -> Vec<usize> {
        vec![]
    }
}

impl<T, U, V> Zero<U, Vec<V>> for PowerSet<Of<T>>
    where T: Construct + Count<U> + Zero<U, V>
{
    fn zero(&self, _dim: &U) -> Vec<V> {
        vec![]
    }
}

impl ToIndex<usize, Vec<usize>> for PowerSet<Data> {
    fn to_index(
        &self,
        _dim: &usize,
        pos: &Vec<usize>
    ) -> usize {
        let mut index = 0;
        for &i in pos.iter() {
            index |= 1 << i;
        }
        index
    }
}

impl<T, U, V>
ToIndex<U, Vec<V>> for PowerSet<Of<T>>
    where
        T: Construct + ToIndex<U, V>,
        V: Clone
{
    fn to_index(
        &self,
        dim: &U,
        pos: &Vec<V>
    ) -> usize {
        let of: T = Construct::new();
        let mut index = 0;
        for i in pos.iter() {
            index |= 1 << of.to_index(dim, i);
        }
        index
    }
}

impl ToPos<usize, Vec<usize>> for PowerSet<Data> {
    fn to_pos(
        &self,
        dim: &usize,
        index: usize,
        pos: &mut Vec<usize>
    ) {
        unsafe { pos.set_len(0); }
        for i in 0..*dim {
            if ((index >> i) & 1) == 1 {
                pos.push(i);
            }
        }
    }
}

impl<T, U, V>
ToPos<U, Vec<V>>
for PowerSet<Of<T>>
    where T: Construct + Count<U, N = usize> + ToPos<U, V> + Zero<U, V>
{
    fn to_pos(
        &self,
        dim: &U,
        index: usize,
        pos: &mut Vec<V>
    ) {
        let of: T = Construct::new();
        let count = of.count(dim);
        pos.clear();
        pos.reserve_exact(count);
        for j in 0..count {
            if ((index >> j) & 1) == 1 {
                let mut p = of.zero(dim);
                of.to_pos(dim, j, &mut p);
                pos.push(p);
            }
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<PowerSet, usize, Vec<usize>>();
        is_complete::<PowerSet<Of<Pair>>, usize, Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let x: PowerSet = Construct::new();
        let ref dim = 6;
        assert_eq!(x.count(dim), 64);
        assert_eq!(x.to_index(dim, &vec![]), 0);
        assert_eq!(x.to_index(dim, &vec![0]), 1);
        assert_eq!(x.to_index(dim, &vec![1]), 2);
        assert_eq!(x.to_index(dim, &vec![0, 1]), 3);
        let mut a = vec![];
        x.to_pos(dim, 9, &mut a);
        assert_eq!(&a, &[0, 3]);
    }

    #[test]
    fn of() {
        let x: PowerSet<Of<Pair>> = Construct::new();
        let ref dim = 4;
        assert_eq!(x.count(dim), 64);
        assert_eq!(x.to_index(dim, &vec![]), 0);
        assert_eq!(x.to_index(dim, &vec![(0, 1)]), 1);
        assert_eq!(x.to_index(dim, &vec![(0, 2)]), 2);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2)]), 3);
        assert_eq!(x.to_index(dim, &vec![(1, 2)]), 4);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (1, 2)]), 5);
        assert_eq!(x.to_index(dim, &vec![(0, 2), (1, 2)]), 6);
        assert_eq!(x.to_index(dim, &vec![(0, 1), (0, 2), (1, 2)]), 7);
        let mut a = vec![(0, 0); 64];
        x.to_pos(dim, 7, &mut a);
        assert_eq!(a[0], (0, 1));
    }
}
<|endoftext|>


<commit_before>use std::{result, io, fmt};

#[derive(Debug, Clone)]
pub enum Error {
    Io(io::Error),
    NotFound,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NotFound => write!(f, "not found"),
            Error::Io(ref error) => fmt::Display::fmt(error, f),
        }
    }
}

pub type Result<T> = result::Result<T, Error>;
<commit_msg>raft: update error.<commit_after>use std::{result, io, fmt};
use std::error;

use protobuf::ProtobufError;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    NotFound,
    Protobuf(ProtobufError),
    Other(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NotFound => write!(f, "not found"),
            Error::Io(ref error) => fmt::Display::fmt(error, f),
            _ => fmt::Display::fmt(self, f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &Error::Io(ref e) => e.description(),
            &Error::NotFound => "not found",
            &Error::Protobuf(ref e) => e.description(),
            &Error::Other(ref e) => &e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Io(ref e) => Some(e),
            &Error::Protobuf(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error{
        Error::Io(err)
    }
 }

impl From<ProtobufError> for Error {
    fn from(err: ProtobufError) -> Error{
        Error::Protobuf(err)
    }
 }

pub type Result<T> = result::Result<T, Error>;
<|endoftext|>


<commit_before>use common::types::{
	Ty,
	bool_ty
};

use util::boxed::{
	ToBoxedVec,
};

#[derive(Clone)]
pub struct Expr (pub Ty, pub ExprKind);

impl Expr
{
	#[inline]
	pub fn ty(&self) -> &Ty
	{
		&self.0
	}

	#[inline]
	pub fn kind(&self) -> &ExprKind
	{
		&self.1
	}
}

/// Expression Specific Element
#[derive(Clone)]
pub enum ExprKind {
  // Unary Expressions
  Not      (Box<Expr>),
  IsNull   (Box<Expr>),
  IsNotNull(Box<Expr>),
  PlusSign (Box<Expr>),
  MinusSign(Box<Expr>),
  Cast     (Box<Expr>, Ty, Ty),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Cmp(CmpOp, Box<Expr>, Box<Expr>),
  Arithm(ArithmOp, Box<Expr>, Box<Expr>),

  // function and values
  Fn(FnDecl, Vec<Box<Expr>>),
  Field(String),
  Const(Literal),

  // condition
  Switch(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  Case  (Box<Expr>, Box<Expr>),      // condition, return value
}

/// Comparison Operator Type
#[derive(Clone, Copy)]
pub enum CmpOp {
  Eq,
  Ne,
  Lt,
  Le,
  Gt,
  Ge
}

/// Arithmetic Operator Type
#[derive(Clone, Copy)]
pub enum ArithmOp {
  Plus,
  Sub,
  Mul,
  Div,
  Rem,
}

/// Function Declaration
#[derive(Clone)]
pub struct FnDecl {
  signature: String,
  ret_ty: Ty
}

impl FnDecl
{
	pub fn ty(&self) -> &Ty
	{
		&self.ret_ty
	}
}

/// Representation for a single value
#[derive(Clone)]
pub enum Literal
{
  Bool(bool),
  I8(i8),
  I16(i16),
  I32(i32),
  I64(i64),
  F32(f32),
  F64(f64),
  String(String)
}

#[allow(non_snake_case)]
pub fn Not(c: Expr) -> Expr
{
	Expr(c.ty().clone(), ExprKind::Not(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn IsNull(c: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::IsNull(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn IsNotNull(c: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::IsNull(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn Cast(c: Expr, from_ty: &Ty, to_ty: &Ty) -> Expr
{
	Expr(to_ty.clone(), ExprKind::Cast(Box::new(c), from_ty.clone(), to_ty.clone()))
}

#[allow(non_snake_case)]
pub fn PlusSign(c: Expr) -> Expr
{
	Expr(c.ty().	clone(), ExprKind::PlusSign(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn MinusSign(c: Expr) -> Expr
{
	Expr(c.ty().clone(), ExprKind::MinusSign(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn And(l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::And(Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Or(l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::Or(Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Cmp(op: CmpOp, l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::Cmp(op, Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Arithm(op: &ArithmOp, ret_type: &Ty, l: Expr, r: Expr) -> Expr
{
	Expr(ret_type.clone(), ExprKind::Arithm(*op, Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Func(decl: FnDecl, args: Vec<Expr>) -> Expr
{
	Expr(decl.ty().clone(), ExprKind::Fn(decl, args.to_boxed()))
}

#[allow(non_snake_case)]
pub fn Switch(cases: Vec<Expr>, default: Expr) -> Expr
{
	Expr(default.ty().clone(), ExprKind::Switch(cases.to_boxed(), Box::new(default)))
}

#[allow(non_snake_case)]
pub fn Case(cond: Expr, result: Expr) -> Expr
{
	Expr(result.ty().clone(), ExprKind::Case(Box::new(cond), Box::new(result)))
}

#[allow(non_snake_case)]
pub fn Const(value: Literal) -> Expr
{
	let ty = match value {
		Literal::Bool(_) => bool_ty(),
		_                => panic!("unsupported type")
	};

	Expr(ty, ExprKind::Const(value))
}

#[allow(non_snake_case)]
pub fn Field(name: String, ty: Ty) -> Expr
{
	Expr(ty, ExprKind::Field(name))
}

pub fn clone(e: &Box<Expr>) -> Expr
{
	*(e.clone())
}

pub mod optimizer
{
	pub use expr_optimizer::*;
}

pub mod visitor
{
	//! Visitor for Expr
	use super::*;

	/// Simple visitor to walk all Expr node in a single accept function.
	/// It provides an easier way to rewrite a Expr tree.
	pub trait Visitor: Sized
	{
	  fn accept(&mut self, e: &Expr)
	  {
	    accept_by_default(self, e);
	  }
	}

	pub fn accept_by_default<T>(v: &mut T, e: &Expr) where T: Visitor + Sized {
	  match *e.kind() {
	    ExprKind::Not      (ref c)       => v.accept(c),
	    ExprKind::IsNull   (ref c)       => v.accept(c),
	    ExprKind::IsNotNull(ref c)       => v.accept(c),
	    ExprKind::PlusSign (ref c)       => v.accept(c),
	    ExprKind::MinusSign(ref c)       => v.accept(c),
	    ExprKind::Cast     (ref c, _, _) => v.accept(c),

	    ExprKind::And      (ref l, ref r)    => { v.accept(l); v.accept(r) },
	    ExprKind::Or       (ref l, ref r)    => { v.accept(l); v.accept(r) },
	    ExprKind::Cmp      (_, ref l, ref r) => { v.accept(l); v.accept(r) },
	    ExprKind::Arithm   (_, ref l, ref r) => { v.accept(l); v.accept(r) },

	    ExprKind::Fn     (_, ref args)  => { for e in args.iter() { v.accept(e) } },
			ExprKind::Field  (_) 	          => {},
	    ExprKind::Const  (_)            => {}

	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },
	  }
	}

	/// Simple visitor to walk all Expr node in a single accept function.
	/// It provides an easier way to rewrite a Expr tree.
	pub trait TransformVisitor: Sized
  {
	  fn transform(&self, e: &Expr) -> Expr
	  {
	    transform_by_default(self, e)
	  }
	}

	pub fn transform_by_default<T>(v: &T, e: &Expr) -> Expr
			where T: TransformVisitor + Sized
	{
		match *e.kind() {
	    ExprKind::Not      (ref c)               => Not      (v.transform(c)),
	    ExprKind::IsNull   (ref c)               => IsNull   (v.transform(c)),
	    ExprKind::IsNotNull(ref c)               => IsNotNull(v.transform(c)),
	    ExprKind::PlusSign (ref c)               => PlusSign (v.transform(c)),
	    ExprKind::MinusSign(ref c)               => MinusSign(v.transform(c)),
	    ExprKind::Cast     (ref c, ref f, ref t) => Cast     (v.transform(c), f, t),

	    ExprKind::And      (ref l, ref r)        => And(v.transform(l), v.transform(r)),
	    ExprKind::Or       (ref l, ref r)        => Or (v.transform(l), v.transform(r)),
	    ExprKind::Cmp      (ref o, ref l, ref r) => Cmp(*o, v.transform(l), v.transform(r)),
	    ExprKind::Arithm   (ref o, ref l, ref r) => Arithm(o, e.ty(), v.transform(l), v.transform(r)),

	    ExprKind::Fn       (ref f, ref args)     => {
	    	let rargs = args.iter().map(|arg| v.transform(arg)).collect::<Vec<Expr>>();
	    	Func(f.clone(), rargs)
    	},
			ExprKind::Field     (_) 	                => e.clone(),
	    ExprKind::Const     (_)                   => e.clone(),

	    ExprKind::Switch   (ref cases, ref default)  => {
	    	let rcases = cases.iter().map(|case| v.transform(case)).collect::<Vec<Expr>>();

	    	Switch(rcases, v.transform(default))
   	  }
	    ExprKind::Case      (ref l, ref r)        => Case(v.transform(l), v.transform(r)),
	  }
	}
}<commit_msg>Implemented into_literal macro and implemented Into trait for all types.<commit_after>use common::types::{
	Ty,
	bool_ty
};

use util::boxed::{
	ToBoxedVec,
};

#[derive(Clone)]
pub struct Expr (pub Ty, pub ExprKind);

impl Expr
{
	#[inline]
	pub fn ty(&self) -> &Ty
	{
		&self.0
	}

	#[inline]
	pub fn kind(&self) -> &ExprKind
	{
		&self.1
	}
}

/// Expression Specific Element
#[derive(Clone)]
pub enum ExprKind {
  // Unary Expressions
  Not      (Box<Expr>),
  IsNull   (Box<Expr>),
  IsNotNull(Box<Expr>),
  PlusSign (Box<Expr>),
  MinusSign(Box<Expr>),
  Cast     (Box<Expr>, Ty, Ty),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Cmp(CmpOp, Box<Expr>, Box<Expr>),
  Arithm(ArithmOp, Box<Expr>, Box<Expr>),

  // function and values
  Fn(FnDecl, Vec<Box<Expr>>),
  Field(String),
  Const(Literal),

  // condition
  Switch(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  Case  (Box<Expr>, Box<Expr>),      // condition, return value
}

/// Comparison Operator Type
#[derive(Clone, Copy)]
pub enum CmpOp {
  Eq,
  Ne,
  Lt,
  Le,
  Gt,
  Ge
}

/// Arithmetic Operator Type
#[derive(Clone, Copy)]
pub enum ArithmOp {
  Plus,
  Sub,
  Mul,
  Div,
  Rem,
}

/// Function Declaration
#[derive(Clone)]
pub struct FnDecl {
  signature: String,
  ret_ty: Ty
}

impl FnDecl
{
	pub fn ty(&self) -> &Ty
	{
		&self.ret_ty
	}
}

/// Representation for a single value
#[derive(Clone)]
pub enum Literal
{
  Bool(bool),
  I8(i8),
  I16(i16),
  I32(i32),
  I64(i64),
  F32(f32),
  F64(f64),
  String(String)
}

macro_rules! into_literal(
	($ty:ty, $literal_kind:ident) => (
    impl Into<Literal> for $ty {
	    fn into(self) -> Literal
	    {
	    	Literal::$literal_kind(self)
	    }
    }
  );
);

into_literal!(bool, Bool);
into_literal!(i8,   I8);
into_literal!(i16,  I16);
into_literal!(i32,  I32);
into_literal!(i64,  I64);
into_literal!(f32,  F32);
into_literal!(f64,  F64);

#[allow(non_snake_case)]
pub fn Not(c: Expr) -> Expr
{
	Expr(c.ty().clone(), ExprKind::Not(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn IsNull(c: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::IsNull(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn IsNotNull(c: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::IsNull(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn Cast(c: Expr, from_ty: &Ty, to_ty: &Ty) -> Expr
{
	Expr(to_ty.clone(), ExprKind::Cast(Box::new(c), from_ty.clone(), to_ty.clone()))
}

#[allow(non_snake_case)]
pub fn PlusSign(c: Expr) -> Expr
{
	Expr(c.ty().	clone(), ExprKind::PlusSign(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn MinusSign(c: Expr) -> Expr
{
	Expr(c.ty().clone(), ExprKind::MinusSign(Box::new(c)))
}

#[allow(non_snake_case)]
pub fn And(l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::And(Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Or(l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::Or(Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Cmp(op: CmpOp, l: Expr, r: Expr) -> Expr
{
	Expr(bool_ty(), ExprKind::Cmp(op, Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Arithm(op: &ArithmOp, ret_type: &Ty, l: Expr, r: Expr) -> Expr
{
	Expr(ret_type.clone(), ExprKind::Arithm(*op, Box::new(l), Box::new(r)))
}

pub fn Subtract(ret_type: &Ty, l: Expr, r: Expr) -> Expr {
	Expr(ret_type.clone(), ExprKind::Arithm(ArithmOp::Sub, Box::new(l), Box::new(r)))
}

pub fn Mul(ret_type: &Ty, l: Expr, r: Expr) -> Expr {
	Expr(ret_type.clone(), ExprKind::Arithm(ArithmOp::Mul, Box::new(l), Box::new(r)))
}

#[allow(non_snake_case)]
pub fn Func(decl: FnDecl, args: Vec<Expr>) -> Expr
{
	Expr(decl.ty().clone(), ExprKind::Fn(decl, args.to_boxed()))
}

#[allow(non_snake_case)]
pub fn Switch(cases: Vec<Expr>, default: Expr) -> Expr
{
	Expr(default.ty().clone(), ExprKind::Switch(cases.to_boxed(), Box::new(default)))
}

#[allow(non_snake_case)]
pub fn Case(cond: Expr, result: Expr) -> Expr
{
	Expr(result.ty().clone(), ExprKind::Case(Box::new(cond), Box::new(result)))
}

#[allow(non_snake_case)]
pub fn Const<T: Into<Literal>>(value: T) -> Expr
{
	let literal = value.into();
	let ty = match literal {
		Literal::Bool(_) => bool_ty(),
		_                => panic!("unsupported type")
	};

	Expr(ty, ExprKind::Const(literal))
}

#[allow(non_snake_case)]
pub fn Field(name: String, ty: Ty) -> Expr
{
	Expr(ty, ExprKind::Field(name))
}

pub fn clone(e: &Box<Expr>) -> Expr
{
	*(e.clone())
}

pub mod optimizer
{
	pub use expr_optimizer::*;
}

pub mod visitor
{
	//! Visitor for Expr
	use super::*;

	/// Simple visitor to walk all Expr node in a single accept function.
	/// It provides an easier way to rewrite a Expr tree.
	pub trait Visitor: Sized
	{
	  fn accept(&mut self, e: &Expr)
	  {
	    accept_by_default(self, e);
	  }
	}

	pub fn accept_by_default<T>(v: &mut T, e: &Expr) where T: Visitor + Sized {
	  match *e.kind() {
	    ExprKind::Not      (ref c)       => v.accept(c),
	    ExprKind::IsNull   (ref c)       => v.accept(c),
	    ExprKind::IsNotNull(ref c)       => v.accept(c),
	    ExprKind::PlusSign (ref c)       => v.accept(c),
	    ExprKind::MinusSign(ref c)       => v.accept(c),
	    ExprKind::Cast     (ref c, _, _) => v.accept(c),

	    ExprKind::And      (ref l, ref r)    => { v.accept(l); v.accept(r) },
	    ExprKind::Or       (ref l, ref r)    => { v.accept(l); v.accept(r) },
	    ExprKind::Cmp      (_, ref l, ref r) => { v.accept(l); v.accept(r) },
	    ExprKind::Arithm   (_, ref l, ref r) => { v.accept(l); v.accept(r) },

	    ExprKind::Fn     (_, ref args)  => { for e in args.iter() { v.accept(e) } },
			ExprKind::Field  (_) 	          => {},
	    ExprKind::Const  (_)            => {}

	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },
	  }
	}

	/// Simple visitor to walk all Expr node in a single accept function.
	/// It provides an easier way to rewrite a Expr tree.
	pub trait TransformVisitor: Sized
  {
	  fn transform(&self, e: &Expr) -> Expr
	  {
	    transform_by_default(self, e)
	  }
	}

	pub fn transform_by_default<T>(v: &T, e: &Expr) -> Expr
			where T: TransformVisitor + Sized
	{
		match *e.kind() {
	    ExprKind::Not      (ref c)               => Not      (v.transform(c)),
	    ExprKind::IsNull   (ref c)               => IsNull   (v.transform(c)),
	    ExprKind::IsNotNull(ref c)               => IsNotNull(v.transform(c)),
	    ExprKind::PlusSign (ref c)               => PlusSign (v.transform(c)),
	    ExprKind::MinusSign(ref c)               => MinusSign(v.transform(c)),
	    ExprKind::Cast     (ref c, ref f, ref t) => Cast     (v.transform(c), f, t),

	    ExprKind::And      (ref l, ref r)        => And(v.transform(l), v.transform(r)),
	    ExprKind::Or       (ref l, ref r)        => Or (v.transform(l), v.transform(r)),
	    ExprKind::Cmp      (ref o, ref l, ref r) => Cmp(*o, v.transform(l), v.transform(r)),
	    ExprKind::Arithm   (ref o, ref l, ref r) => Arithm(o, e.ty(), v.transform(l), v.transform(r)),

	    ExprKind::Fn       (ref f, ref args)     => {
	    	let rargs = args.iter().map(|arg| v.transform(arg)).collect::<Vec<Expr>>();
	    	Func(f.clone(), rargs)
    	},
			ExprKind::Field     (_) 	                => e.clone(),
	    ExprKind::Const     (_)                   => e.clone(),

	    ExprKind::Switch   (ref cases, ref default)  => {
	    	let rcases = cases.iter().map(|case| v.transform(case)).collect::<Vec<Expr>>();

	    	Switch(rcases, v.transform(default))
   	  }
	    ExprKind::Case      (ref l, ref r)        => Case(v.transform(l), v.transform(r)),
	  }
	}
}<|endoftext|>


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

use crate::filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
where
    F: Filter<T>,
    I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
where
    F: Filter<T>,
    I: Iterator<Item = T>,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>>: Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
where
    I: Iterator<Item = T>,
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

pub struct FilterOksIter<T, E, I, F>(I, F)
where
    F: Filter<T>,
    I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterOksIter<T, E, I, F>
where
    F: Filter<T>,
    I: Iterator<Item = Result<T, E>>,
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Err(e) => return Some(Err(e)),
                Ok(t) => {
                    if self.1.filter(&t) {
                        return Some(Ok(t));
                    }
                }
            }
        }

        None
    }
}

pub trait FilterOks<T, E, I, F>: Iterator<Item = Result<T, E>>
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<T>,
{
    fn filter_oks(self, _: F) -> FilterOksIter<T, E, I, F>;
}

impl<T, E, I, F> FilterOks<T, E, I, F> for I
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<T>,
{
    fn filter_oks(self, f: F) -> FilterOksIter<T, E, I, F> {
        FilterOksIter(self, f)
    }
}

pub struct FilterErrIter<T, E, I, F>(I, F)
where
    F: Filter<E>,
    I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterErrIter<T, E, I, F>
where
    F: Filter<E>,
    I: Iterator<Item = Result<T, E>>,
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Ok(t) => return Some(Ok(t)),
                Err(e) => {
                    if self.1.filter(&e) {
                        return Some(Err(e));
                    }
                }
            }
        }

        None
    }
}

pub trait FilterErr<T, E, I, F>: Iterator<Item = Result<T, E>>
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<E>,
{
    fn filter_errs(self, _: F) -> FilterErrIter<T, E, I, F>;
}

impl<T, E, I, F> FilterErr<T, E, I, F> for I
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<E>,
{
    fn filter_errs(self, f: F) -> FilterErrIter<T, E, I, F> {
        FilterErrIter(self, f)
    }
}

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

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(f)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }

    #[test]
    fn test_filter_oks() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<Result<u64, u64>> = vec![
            Ok(1),
            Err(2),
            Ok(3),
            Err(4),
            Ok(5),
            Err(6),
            Ok(7),
            Err(8),
            Ok(9),
            Err(0),
        ]
        .into_iter()
        .filter_oks(f)
        .collect();

        assert_eq!(
            v,
            vec![Err(2), Err(4), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
        );
    }

    #[test]
    fn test_filter_errs() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<Result<u64, u64>> = vec![
            Ok(1),
            Err(2),
            Ok(3),
            Err(4),
            Ok(5),
            Err(6),
            Ok(7),
            Err(8),
            Ok(9),
            Err(0),
        ]
        .into_iter()
        .filter_errs(f)
        .collect();

        assert_eq!(v, vec![Ok(1), Ok(3), Ok(5), Err(6), Ok(7), Err(8), Ok(9)]);
    }
}
<commit_msg>Fix clippy: use by_ref()<commit_after>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use crate::filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
where
    F: Filter<T>,
    I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
where
    F: Filter<T>,
    I: Iterator<Item = T>,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.by_ref().next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>>: Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
where
    I: Iterator<Item = T>,
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

pub struct FilterOksIter<T, E, I, F>(I, F)
where
    F: Filter<T>,
    I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterOksIter<T, E, I, F>
where
    F: Filter<T>,
    I: Iterator<Item = Result<T, E>>,
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.by_ref().next() {
            match next {
                Err(e) => return Some(Err(e)),
                Ok(t) => {
                    if self.1.filter(&t) {
                        return Some(Ok(t));
                    }
                }
            }
        }

        None
    }
}

pub trait FilterOks<T, E, I, F>: Iterator<Item = Result<T, E>>
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<T>,
{
    fn filter_oks(self, _: F) -> FilterOksIter<T, E, I, F>;
}

impl<T, E, I, F> FilterOks<T, E, I, F> for I
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<T>,
{
    fn filter_oks(self, f: F) -> FilterOksIter<T, E, I, F> {
        FilterOksIter(self, f)
    }
}

pub struct FilterErrIter<T, E, I, F>(I, F)
where
    F: Filter<E>,
    I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterErrIter<T, E, I, F>
where
    F: Filter<E>,
    I: Iterator<Item = Result<T, E>>,
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.by_ref().next() {
            match next {
                Ok(t) => return Some(Ok(t)),
                Err(e) => {
                    if self.1.filter(&e) {
                        return Some(Err(e));
                    }
                }
            }
        }

        None
    }
}

pub trait FilterErr<T, E, I, F>: Iterator<Item = Result<T, E>>
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<E>,
{
    fn filter_errs(self, _: F) -> FilterErrIter<T, E, I, F>;
}

impl<T, E, I, F> FilterErr<T, E, I, F> for I
where
    I: Iterator<Item = Result<T, E>>,
    F: Filter<E>,
{
    fn filter_errs(self, f: F) -> FilterErrIter<T, E, I, F> {
        FilterErrIter(self, f)
    }
}

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

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(f)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }

    #[test]
    fn test_filter_oks() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<Result<u64, u64>> = vec![
            Ok(1),
            Err(2),
            Ok(3),
            Err(4),
            Ok(5),
            Err(6),
            Ok(7),
            Err(8),
            Ok(9),
            Err(0),
        ]
        .into_iter()
        .filter_oks(f)
        .collect();

        assert_eq!(
            v,
            vec![Err(2), Err(4), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
        );
    }

    #[test]
    fn test_filter_errs() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let f = Foo;

        let v: Vec<Result<u64, u64>> = vec![
            Ok(1),
            Err(2),
            Ok(3),
            Err(4),
            Ok(5),
            Err(6),
            Ok(7),
            Err(8),
            Ok(9),
            Err(0),
        ]
        .into_iter()
        .filter_errs(f)
        .collect();

        assert_eq!(v, vec![Ok(1), Ok(3), Ok(5), Err(6), Ok(7), Err(8), Ok(9)]);
    }
}
<|endoftext|>