<commit_before>#![feature(deque_extras)]
#![feature(box_syntax)]
#![feature(plugin)]
#![plugin(peg_syntax_ext)]

extern crate glob;

use std::collections::HashMap;
use std::fs::File;
use std::io::{stdout, Read, Write};
use std::env;
use std::process;

use self::directory_stack::DirectoryStack;
use self::input_editor::readln;
use self::peg::{parse, Job, Pipeline};
use self::variables::Variables;
use self::history::History;
use self::flow_control::{FlowControl, is_flow_control_command, Statement};
use self::status::SUCCESS;
use self::function::Function;
use self::pipe::execute_pipeline;

pub mod pipe;
pub mod directory_stack;
pub mod to_num;
pub mod input_editor;
pub mod peg;
pub mod variables;
pub mod history;
pub mod flow_control;
pub mod status;
pub mod function;

/// This struct will contain all of the data structures related to this
/// instance of the shell.
pub struct Shell {
    variables: Variables,
    flow_control: FlowControl,
    directory_stack: DirectoryStack,
    history: History,
    functions: HashMap<String, Function>
}

impl Shell {
    /// Panics if DirectoryStack construction fails
    pub fn new() -> Self {
        let mut new_shell = Shell {
            variables: Variables::new(),
            flow_control: FlowControl::new(),
            directory_stack: DirectoryStack::new().expect(""),
            history: History::new(),
            functions: HashMap::new()
        };
        new_shell.initialize_default_variables();
        new_shell.evaluate_init_file();
        return new_shell;
    }

    /// This function will initialize the default variables used by the shell. This function will
    /// be called before evaluating the init
    fn initialize_default_variables(&mut self) {
        self.variables.set_var("DIRECTORY_STACK_SIZE", "1000");
        self.variables.set_var("HISTORY_SIZE", "1000");
        self.variables.set_var("HISTORY_FILE_ENABLED", "1");
        self.variables.set_var("PROMPT", "ion:$CWD# ");

        {   // Initialize the HISTORY_FILE variable
            let mut history_path = std::env::home_dir().unwrap();
            history_path.push(".ion_history");
            self.variables.set_var("HISTORY_FILE", history_path.to_str().unwrap());
        }

        {   // Initialize the CWD (Current Working Directory) variable
            match std::env::current_dir() {
                Ok(path) => self.variables.set_var("CWD", path.to_str().unwrap()),
                Err(_)   => self.variables.set_var("CWD", "?")
            }
        }
    }

    /// This functional will update variables that need to be kept consistent with each iteration
    /// of the prompt. In example, the CWD variable needs to be updated to reflect changes to the
    /// the current working directory.
    fn update_variables(&mut self) {
        {   // Update the CWD (Current Working Directory) variable
            match std::env::current_dir() {
                Ok(path) => self.variables.set_var("CWD", path.to_str().unwrap()),
                Err(_)   => self.variables.set_var("CWD", "?")
            }
        }
    }

    /// Evaluates the source init file in the user's home directory. If the file does not exist,
    /// the file will be created.
    fn evaluate_init_file(&mut self) {
        let commands = &Command::map();
        let mut source_file = std::env::home_dir().unwrap(); // Obtain home directory
        source_file.push(".ionrc");                          // Location of ion init file

        if let Ok(mut file) = File::open(source_file.clone()) {
            let mut command_list = String::new();
            if let Err(message) = file.read_to_string(&mut command_list) {
                println!("{}: Failed to read {:?}", message, source_file.clone());
            } else {
                self.on_command(&command_list, commands);
            }
        } else {
            if let Err(message) = File::create(source_file) {
                println!("{}", message);
            }
        }
    }

    pub fn print_prompt(&self) {
        self.print_prompt_prefix();
        match self.flow_control.current_statement {
            Statement::For(_, _) => self.print_for_prompt(),
            Statement::Function(_) => self.print_function_prompt(),
            _ => self.print_default_prompt(),
        }
        if let Err(message) = stdout().flush() {
            println!("{}: failed to flush prompt to stdout", message);
        }

    }

    // TODO eventually this thing should be gone
    fn print_prompt_prefix(&self) {
        let prompt_prefix = self.flow_control.modes.iter().rev().fold(String::new(), |acc, mode| {
            acc +
            if mode.value {
                "+ "
            } else {
                "- "
            }
        });
        print!("{}", prompt_prefix);
    }

    fn print_for_prompt(&self) {
        print!("for> ");
    }

    fn print_function_prompt(&self) {
        print!("fn> ");
    }

    fn print_default_prompt(&self) {
        print!("{}", self.variables.expand_string(&self.variables.expand_string("$PROMPT")));
    }

    fn on_command(&mut self, command_string: &str, commands: &HashMap<&str, Command>) {
        self.history.add(command_string.to_string(), &self.variables);

        let mut pipelines = parse(command_string);

        // Execute commands
        for pipeline in pipelines.drain(..) {
            if self.flow_control.collecting_block {
                // TODO move this logic into "end" command
                if pipeline.jobs[0].command == "end" {
                    self.flow_control.collecting_block = false;
                    let block_jobs: Vec<Pipeline> = self.flow_control
                                                   .current_block
                                                   .pipelines
                                                   .drain(..)
                                                   .collect();
                    match self.flow_control.current_statement.clone() {
                        Statement::For(ref var, ref vals) => {
                            let variable = var.clone();
                            let values = vals.clone();
                            for value in values {
                                self.variables.set_var(&variable, &value);
                                for pipeline in block_jobs.iter() {
                                    self.run_pipeline(&pipeline, commands);
                                }
                            }
                        },
                        Statement::Function(ref name) => {
                            self.functions.insert(name.clone(), Function { name: name.clone(), pipelines: block_jobs.clone() });
                        },
                        _ => {}
                    }
                    self.flow_control.current_statement = Statement::Default;
                } else {
                    self.flow_control.current_block.pipelines.push(pipeline);
                }
            } else {
                if self.flow_control.skipping() && !is_flow_control_command(&pipeline.jobs[0].command) {
                    continue;
                }
                self.run_pipeline(&pipeline, commands);
            }
        }
    }

    fn run_pipeline(&mut self, pipeline: &Pipeline, commands: &HashMap<&str, Command>) -> Option<i32> {
        let mut pipeline = self.variables.expand_pipeline(pipeline);
        pipeline.expand_globs();
        let exit_status = if let Some(command) = commands.get(pipeline.jobs[0].command.as_str()) {
            Some((*command.main)(pipeline.jobs[0].args.as_slice(), self))
        } else if self.functions.get(pipeline.jobs[0].command.as_str()).is_some() {
            // Not really idiomatic but I don't know how to clone the value without borrowing self
            let function = self.functions.get(pipeline.jobs[0].command.as_str()).unwrap().clone();
            let mut return_value = None;
            for function_pipeline in function.pipelines.iter() {
                return_value = self.run_pipeline(function_pipeline, commands)
            }
            return_value
        } else {
            Some(execute_pipeline(pipeline))
        };
        if let Some(code) = exit_status {
            self.variables.set_var("?", &code.to_string());
            self.history.previous_status = code;
        }
        exit_status
    }

    pub fn build_command(job: &Job) -> process::Command {
        let mut command = process::Command::new(&job.command);
        for i in 1..job.args.len() {
            if let Some(arg) = job.args.get(i) {
                command.arg(arg);
            }
        }
        command
    }

    /// Evaluates the given file and returns 'SUCCESS' if it succeeds.
    fn source_command(&mut self, arguments: &[String]) -> i32 {
        let commands = Command::map();
        match arguments.iter().skip(1).next() {
            Some(argument) => {
                if let Ok(mut file) = File::open(&argument) {
                    let mut command_list = String::new();
                    if let Err(message) = file.read_to_string(&mut command_list) {
                        println!("{}: Failed to read {}", message, argument);
                        return status::FAILURE;
                    } else {
                        self.on_command(&command_list, &commands);
                        return status::SUCCESS;
                    }
                } else {
                    println!("Failed to open {}", argument);
                    return status::FAILURE;
                }
            },
            None => {
                self.evaluate_init_file();
                return status::SUCCESS;
            },
        }
    }
}

/// Structure which represents a Terminal's command.
/// This command structure contains a name, and the code which run the
/// functionnality associated to this one, with zero, one or several argument(s).
/// # Example
/// ```
/// let my_command = Command {
///     name: "my_command",
///     help: "Describe what my_command does followed by a newline showing usage",
///     main: box|args: &[String], &mut Shell| -> i32 {
///         println!("Say 'hello' to my command! :-D");
///     }
/// }
/// ```
pub struct Command {
    pub name: &'static str,
    pub help: &'static str,
    pub main: Box<Fn(&[String], &mut Shell) -> i32>,
}

impl Command {
    /// Return the map from command names to commands
    pub fn map() -> HashMap<&'static str, Self> {
        let mut commands: HashMap<&str, Self> = HashMap::new();

        commands.insert("cd",
                        Command {
                            name: "cd",
                            help: "Change the current directory\n    cd <path>",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.cd(args, &shell.variables)
                            },
                        });

        commands.insert("dirs",
                        Command {
                            name: "dirs",
                            help: "Display the current directory stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.dirs(args)
                            },
                        });

        commands.insert("exit",
                        Command {
                            name: "exit",
                            help: "To exit the curent session",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                if let Some(status) = args.get(1) {
                                    if let Ok(status) = status.parse::<i32>() {
                                        process::exit(status);
                                    }
                                }
                                process::exit(shell.history.previous_status);
                            },
                        });

        commands.insert("let",
                        Command {
                            name: "let",
                            help: "View, set or unset variables",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.variables.let_(args)
                            },
                        });

        commands.insert("read",
                        Command {
                            name: "read",
                            help: "Read some variables\n    read <variable>",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.variables.read(args)
                            },
                        });

        commands.insert("pushd",
                        Command {
                            name: "pushd",
                            help: "Push a directory to the stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.pushd(args, &shell.variables)
                            },
                        });

        commands.insert("popd",
                        Command {
                            name: "popd",
                            help: "Pop a directory from the stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.popd(args)
                            },
                        });

        commands.insert("history",
                        Command {
                            name: "history",
                            help: "Display a log of all commands previously executed",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.history.history(args)
                            },
                        });

        commands.insert("if",
                        Command {
                            name: "if",
                            help: "Conditionally execute code",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.if_(args)
                            },
                        });

        commands.insert("else",
                        Command {
                            name: "else",
                            help: "Execute code if a previous condition was false",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.else_(args)
                            },
                        });

        commands.insert("end",
                        Command {
                            name: "end",
                            help: "End a code block",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.end(args)
                            },
                        });

        commands.insert("for",
                        Command {
                            name: "for",
                            help: "Iterate through a list",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.for_(args)
                            },
                        });

        commands.insert("source",
                        Command {
                            name: "source",
                            help: "Evaluate the file following the command or re-initialize the init file",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.source_command(args)

                            },
                        });

        commands.insert("fn",
                        Command {
                            name: "fn",
                            help: "Create a function",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.fn_(args)
                            },
                        });

        let command_helper: HashMap<&'static str, &'static str> = commands.iter()
                                                                          .map(|(k, v)| {
                                                                              (*k, v.help)
                                                                          })
                                                                          .collect();

        commands.insert("help",
                        Command {
                            name: "help",
                            help: "Display helpful information about a given command, or list \
                                   commands if none specified\n    help <command>",
                            main: box move |args: &[String], _: &mut Shell| -> i32 {
                                if let Some(command) = args.get(1) {
                                    if command_helper.contains_key(command.as_str()) {
                                        match command_helper.get(command.as_str()) {
                                            Some(help) => println!("{}", help),
                                            None => {
                                                println!("Command helper not found [run 'help']...")
                                            }
                                        }
                                    } else {
                                        println!("Command helper not found [run 'help']...");
                                    }
                                } else {
                                    for (command, _help) in command_helper.iter() {
                                        println!("{}", command);
                                    }
                                }
                                SUCCESS
                            },
                        });

        commands
    }
}

fn main() {
    let commands = Command::map();
    let mut shell = Shell::new();

    let mut dash_c = false;
    for arg in env::args().skip(1) {
        if arg == "-c" {
            dash_c = true;
        } else {
            if dash_c {
                shell.on_command(&arg, &commands);
            } else {
                match File::open(&arg) {
                    Ok(mut file) => {
                        let mut command_list = String::new();
                        match file.read_to_string(&mut command_list) {
                            Ok(_) => shell.on_command(&command_list, &commands),
                            Err(err) => println!("ion: failed to read {}: {}", arg, err)
                        }
                    },
                    Err(err) => println!("ion: failed to open {}: {}", arg, err)
                }
            }

            // Exit with the previous command's exit status.
            process::exit(shell.history.previous_status);
        }
    }

    shell.print_prompt();
    while let Some(command) = readln() {
        let command = command.trim();
        if !command.is_empty() {
            shell.on_command(command, &commands);
        }
        shell.update_variables();
        shell.print_prompt();
    }

    // Exit with the previous command's exit status.
    process::exit(shell.history.previous_status);
}
<commit_msg>Add HOME Variable to Init<commit_after>#![feature(deque_extras)]
#![feature(box_syntax)]
#![feature(plugin)]
#![plugin(peg_syntax_ext)]

extern crate glob;

use std::collections::HashMap;
use std::fs::File;
use std::io::{stdout, Read, Write};
use std::env;
use std::process;

use self::directory_stack::DirectoryStack;
use self::input_editor::readln;
use self::peg::{parse, Job, Pipeline};
use self::variables::Variables;
use self::history::History;
use self::flow_control::{FlowControl, is_flow_control_command, Statement};
use self::status::SUCCESS;
use self::function::Function;
use self::pipe::execute_pipeline;

pub mod pipe;
pub mod directory_stack;
pub mod to_num;
pub mod input_editor;
pub mod peg;
pub mod variables;
pub mod history;
pub mod flow_control;
pub mod status;
pub mod function;

/// This struct will contain all of the data structures related to this
/// instance of the shell.
pub struct Shell {
    variables: Variables,
    flow_control: FlowControl,
    directory_stack: DirectoryStack,
    history: History,
    functions: HashMap<String, Function>
}

impl Shell {
    /// Panics if DirectoryStack construction fails
    pub fn new() -> Self {
        let mut new_shell = Shell {
            variables: Variables::new(),
            flow_control: FlowControl::new(),
            directory_stack: DirectoryStack::new().expect(""),
            history: History::new(),
            functions: HashMap::new()
        };
        new_shell.initialize_default_variables();
        new_shell.evaluate_init_file();
        return new_shell;
    }

    /// This function will initialize the default variables used by the shell. This function will
    /// be called before evaluating the init
    fn initialize_default_variables(&mut self) {
        self.variables.set_var("DIRECTORY_STACK_SIZE", "1000");
        self.variables.set_var("HISTORY_SIZE", "1000");
        self.variables.set_var("HISTORY_FILE_ENABLED", "1");
        self.variables.set_var("HISTORY_FILE_SIZE", "1000");
        self.variables.set_var("PROMPT", "ion:$CWD# ");

        {   // Initialize the HISTORY_FILE variable
            let mut history_path = std::env::home_dir().unwrap();
            history_path.push(".ion_history");
            self.variables.set_var("HISTORY_FILE", history_path.to_str().unwrap_or("?"));
        }

        {   // Initialize the CWD (Current Working Directory) variable
            match std::env::current_dir() {
                Ok(path) => self.variables.set_var("CWD", path.to_str().unwrap_or("?")),
                Err(_)   => self.variables.set_var("CWD", "?")
            }
        }

        {   // Initialize the HOME variable
            match std::env::home_dir() {
                Some(path) => self.variables.set_var("HOME", path.to_str().unwrap_or("?")),
                None       => self.variables.set_var("HOME", "?")
            }
        }
    }

    /// This functional will update variables that need to be kept consistent with each iteration
    /// of the prompt. In example, the CWD variable needs to be updated to reflect changes to the
    /// the current working directory.
    fn update_variables(&mut self) {
        {   // Update the CWD (Current Working Directory) variable
            match std::env::current_dir() {
                Ok(path) => self.variables.set_var("CWD", path.to_str().unwrap()),
                Err(_)   => self.variables.set_var("CWD", "?")
            }
        }
    }

    /// Evaluates the source init file in the user's home directory. If the file does not exist,
    /// the file will be created.
    fn evaluate_init_file(&mut self) {
        let commands = &Command::map();
        let mut source_file = std::env::home_dir().unwrap(); // Obtain home directory
        source_file.push(".ionrc");                          // Location of ion init file

        if let Ok(mut file) = File::open(source_file.clone()) {
            let mut command_list = String::new();
            if let Err(message) = file.read_to_string(&mut command_list) {
                println!("{}: Failed to read {:?}", message, source_file.clone());
            } else {
                self.on_command(&command_list, commands);
            }
        } else {
            if let Err(message) = File::create(source_file) {
                println!("{}", message);
            }
        }
    }

    pub fn print_prompt(&self) {
        self.print_prompt_prefix();
        match self.flow_control.current_statement {
            Statement::For(_, _) => self.print_for_prompt(),
            Statement::Function(_) => self.print_function_prompt(),
            _ => self.print_default_prompt(),
        }
        if let Err(message) = stdout().flush() {
            println!("{}: failed to flush prompt to stdout", message);
        }

    }

    // TODO eventually this thing should be gone
    fn print_prompt_prefix(&self) {
        let prompt_prefix = self.flow_control.modes.iter().rev().fold(String::new(), |acc, mode| {
            acc +
            if mode.value {
                "+ "
            } else {
                "- "
            }
        });
        print!("{}", prompt_prefix);
    }

    fn print_for_prompt(&self) {
        print!("for> ");
    }

    fn print_function_prompt(&self) {
        print!("fn> ");
    }

    fn print_default_prompt(&self) {
        print!("{}", self.variables.expand_string(&self.variables.expand_string("$PROMPT")));
    }

    fn on_command(&mut self, command_string: &str, commands: &HashMap<&str, Command>) {
        self.history.add(command_string.to_string(), &self.variables);

        let mut pipelines = parse(command_string);

        // Execute commands
        for pipeline in pipelines.drain(..) {
            if self.flow_control.collecting_block {
                // TODO move this logic into "end" command
                if pipeline.jobs[0].command == "end" {
                    self.flow_control.collecting_block = false;
                    let block_jobs: Vec<Pipeline> = self.flow_control
                                                   .current_block
                                                   .pipelines
                                                   .drain(..)
                                                   .collect();
                    match self.flow_control.current_statement.clone() {
                        Statement::For(ref var, ref vals) => {
                            let variable = var.clone();
                            let values = vals.clone();
                            for value in values {
                                self.variables.set_var(&variable, &value);
                                for pipeline in block_jobs.iter() {
                                    self.run_pipeline(&pipeline, commands);
                                }
                            }
                        },
                        Statement::Function(ref name) => {
                            self.functions.insert(name.clone(), Function { name: name.clone(), pipelines: block_jobs.clone() });
                        },
                        _ => {}
                    }
                    self.flow_control.current_statement = Statement::Default;
                } else {
                    self.flow_control.current_block.pipelines.push(pipeline);
                }
            } else {
                if self.flow_control.skipping() && !is_flow_control_command(&pipeline.jobs[0].command) {
                    continue;
                }
                self.run_pipeline(&pipeline, commands);
            }
        }
    }

    fn run_pipeline(&mut self, pipeline: &Pipeline, commands: &HashMap<&str, Command>) -> Option<i32> {
        let mut pipeline = self.variables.expand_pipeline(pipeline);
        pipeline.expand_globs();
        let exit_status = if let Some(command) = commands.get(pipeline.jobs[0].command.as_str()) {
            Some((*command.main)(pipeline.jobs[0].args.as_slice(), self))
        } else if self.functions.get(pipeline.jobs[0].command.as_str()).is_some() {
            // Not really idiomatic but I don't know how to clone the value without borrowing self
            let function = self.functions.get(pipeline.jobs[0].command.as_str()).unwrap().clone();
            let mut return_value = None;
            for function_pipeline in function.pipelines.iter() {
                return_value = self.run_pipeline(function_pipeline, commands)
            }
            return_value
        } else {
            Some(execute_pipeline(pipeline))
        };
        if let Some(code) = exit_status {
            self.variables.set_var("?", &code.to_string());
            self.history.previous_status = code;
        }
        exit_status
    }

    pub fn build_command(job: &Job) -> process::Command {
        let mut command = process::Command::new(&job.command);
        for i in 1..job.args.len() {
            if let Some(arg) = job.args.get(i) {
                command.arg(arg);
            }
        }
        command
    }

    /// Evaluates the given file and returns 'SUCCESS' if it succeeds.
    fn source_command(&mut self, arguments: &[String]) -> i32 {
        let commands = Command::map();
        match arguments.iter().skip(1).next() {
            Some(argument) => {
                if let Ok(mut file) = File::open(&argument) {
                    let mut command_list = String::new();
                    if let Err(message) = file.read_to_string(&mut command_list) {
                        println!("{}: Failed to read {}", message, argument);
                        return status::FAILURE;
                    } else {
                        self.on_command(&command_list, &commands);
                        return status::SUCCESS;
                    }
                } else {
                    println!("Failed to open {}", argument);
                    return status::FAILURE;
                }
            },
            None => {
                self.evaluate_init_file();
                return status::SUCCESS;
            },
        }
    }
}

/// Structure which represents a Terminal's command.
/// This command structure contains a name, and the code which run the
/// functionnality associated to this one, with zero, one or several argument(s).
/// # Example
/// ```
/// let my_command = Command {
///     name: "my_command",
///     help: "Describe what my_command does followed by a newline showing usage",
///     main: box|args: &[String], &mut Shell| -> i32 {
///         println!("Say 'hello' to my command! :-D");
///     }
/// }
/// ```
pub struct Command {
    pub name: &'static str,
    pub help: &'static str,
    pub main: Box<Fn(&[String], &mut Shell) -> i32>,
}

impl Command {
    /// Return the map from command names to commands
    pub fn map() -> HashMap<&'static str, Self> {
        let mut commands: HashMap<&str, Self> = HashMap::new();

        commands.insert("cd",
                        Command {
                            name: "cd",
                            help: "Change the current directory\n    cd <path>",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.cd(args, &shell.variables)
                            },
                        });

        commands.insert("dirs",
                        Command {
                            name: "dirs",
                            help: "Display the current directory stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.dirs(args)
                            },
                        });

        commands.insert("exit",
                        Command {
                            name: "exit",
                            help: "To exit the curent session",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                if let Some(status) = args.get(1) {
                                    if let Ok(status) = status.parse::<i32>() {
                                        process::exit(status);
                                    }
                                }
                                process::exit(shell.history.previous_status);
                            },
                        });

        commands.insert("let",
                        Command {
                            name: "let",
                            help: "View, set or unset variables",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.variables.let_(args)
                            },
                        });

        commands.insert("read",
                        Command {
                            name: "read",
                            help: "Read some variables\n    read <variable>",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.variables.read(args)
                            },
                        });

        commands.insert("pushd",
                        Command {
                            name: "pushd",
                            help: "Push a directory to the stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.pushd(args, &shell.variables)
                            },
                        });

        commands.insert("popd",
                        Command {
                            name: "popd",
                            help: "Pop a directory from the stack",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.directory_stack.popd(args)
                            },
                        });

        commands.insert("history",
                        Command {
                            name: "history",
                            help: "Display a log of all commands previously executed",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.history.history(args)
                            },
                        });

        commands.insert("if",
                        Command {
                            name: "if",
                            help: "Conditionally execute code",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.if_(args)
                            },
                        });

        commands.insert("else",
                        Command {
                            name: "else",
                            help: "Execute code if a previous condition was false",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.else_(args)
                            },
                        });

        commands.insert("end",
                        Command {
                            name: "end",
                            help: "End a code block",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.end(args)
                            },
                        });

        commands.insert("for",
                        Command {
                            name: "for",
                            help: "Iterate through a list",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.for_(args)
                            },
                        });

        commands.insert("source",
                        Command {
                            name: "source",
                            help: "Evaluate the file following the command or re-initialize the init file",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.source_command(args)

                            },
                        });

        commands.insert("fn",
                        Command {
                            name: "fn",
                            help: "Create a function",
                            main: box |args: &[String], shell: &mut Shell| -> i32 {
                                shell.flow_control.fn_(args)
                            },
                        });

        let command_helper: HashMap<&'static str, &'static str> = commands.iter()
                                                                          .map(|(k, v)| {
                                                                              (*k, v.help)
                                                                          })
                                                                          .collect();

        commands.insert("help",
                        Command {
                            name: "help",
                            help: "Display helpful information about a given command, or list \
                                   commands if none specified\n    help <command>",
                            main: box move |args: &[String], _: &mut Shell| -> i32 {
                                if let Some(command) = args.get(1) {
                                    if command_helper.contains_key(command.as_str()) {
                                        match command_helper.get(command.as_str()) {
                                            Some(help) => println!("{}", help),
                                            None => {
                                                println!("Command helper not found [run 'help']...")
                                            }
                                        }
                                    } else {
                                        println!("Command helper not found [run 'help']...");
                                    }
                                } else {
                                    for (command, _help) in command_helper.iter() {
                                        println!("{}", command);
                                    }
                                }
                                SUCCESS
                            },
                        });

        commands
    }
}

fn main() {
    let commands = Command::map();
    let mut shell = Shell::new();

    let mut dash_c = false;
    for arg in env::args().skip(1) {
        if arg == "-c" {
            dash_c = true;
        } else {
            if dash_c {
                shell.on_command(&arg, &commands);
            } else {
                match File::open(&arg) {
                    Ok(mut file) => {
                        let mut command_list = String::new();
                        match file.read_to_string(&mut command_list) {
                            Ok(_) => shell.on_command(&command_list, &commands),
                            Err(err) => println!("ion: failed to read {}: {}", arg, err)
                        }
                    },
                    Err(err) => println!("ion: failed to open {}: {}", arg, err)
                }
            }

            // Exit with the previous command's exit status.
            process::exit(shell.history.previous_status);
        }
    }

    shell.print_prompt();
    while let Some(command) = readln() {
        let command = command.trim();
        if !command.is_empty() {
            shell.on_command(command, &commands);
        }
        shell.update_variables();
        shell.print_prompt();
    }

    // Exit with the previous command's exit status.
    process::exit(shell.history.previous_status);
}
<|endoftext|>


<commit_before><commit_msg>Added TODOs and changed log level<commit_after><|endoftext|>


<commit_before><commit_msg>Removes unused parameter<commit_after><|endoftext|>


<commit_before><commit_msg>Ignore late reasons for now.<commit_after><|endoftext|>


<commit_before><commit_msg>Adding main source<commit_after><|endoftext|>


<commit_before>#![crate_name = "clog"]
#![comment = "A conventional changelog generator"]
#![license = "MIT"]
#![feature(macro_rules, phase)]

extern crate regex;
#[phase(plugin)]
extern crate regex_macros;
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate time;

use git::{ LogReaderConfig, get_commits, get_latest_tag };
use log_writer::{ LogWriter, LogWriterOptions };
use section_builder::build_sections;
use std::io::{File, Open, Write};
use docopt::FlagParser;
use time::get_time;

mod common;
mod git;
mod log_writer;
mod section_builder;

docopt!(Args, "clog

Usage:
  clog [--repository=<link> --setversion=<version> --subtitle=<subtitle>
        --from=<from> --to=<to> --from-latest-tag]

Options:
  -h --help               Show this screen.
  --version               Show version
  -r --repository=<link>  e.g https://github.com/thoughtram/clog
  --setversion=<version>  e.g. 0.1.0
  --subtitle=<subtitle>   e.g. crazy-release-name
  --from=<from>           e.g. 12a8546
  --to=<to>               e.g. 8057684
  --from-latest-tag       uses the latest tag as starting point. Ignores other --from parameter")

fn main () {

    let start_nsec = get_time().nsec;
    let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

    let log_reader_config = LogReaderConfig {
        grep: "^feat|^fix|BREAKING'".to_string(),
        format: "%H%n%s%n%b%n==END==".to_string(),
        from: if args.flag_from_latest_tag { get_latest_tag() } else { args.flag_from },
        to: args.flag_to
    };

    let commits = get_commits(log_reader_config);

    let sections = build_sections(commits.clone());
    let contents = File::open(&Path::new("changelog.md")).read_to_string().unwrap();

    let mut file = File::open_mode(&Path::new("changelog.md"), Open, Write).ok().unwrap();
    let mut writer = LogWriter::new(&mut file, LogWriterOptions {
        repository_link: args.flag_repository,
        version: args.flag_setversion,
        subtitle: args.flag_subtitle
    });

    writer.write_header();
    writer.write_section("Bug Fixes", &sections.fixes);
    writer.write_section("Features", &sections.features);
    writer.write(contents.as_slice());

    let end_nsec = get_time().nsec;
    let elapsed_mssec = (end_nsec - start_nsec) / 1000000;
    println!("changelog updated. (took {} ms)", elapsed_mssec);
}
<commit_msg>fix(main): don't fail if changelog.md does not exist<commit_after>#![crate_name = "clog"]
#![comment = "A conventional changelog generator"]
#![license = "MIT"]
#![feature(macro_rules, phase)]

extern crate regex;
#[phase(plugin)]
extern crate regex_macros;
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate time;

use git::{ LogReaderConfig, get_commits, get_latest_tag };
use log_writer::{ LogWriter, LogWriterOptions };
use section_builder::build_sections;
use std::io::{File, Open, Write};
use docopt::FlagParser;
use time::get_time;

mod common;
mod git;
mod log_writer;
mod section_builder;

docopt!(Args, "clog

Usage:
  clog [--repository=<link> --setversion=<version> --subtitle=<subtitle>
        --from=<from> --to=<to> --from-latest-tag]

Options:
  -h --help               Show this screen.
  --version               Show version
  -r --repository=<link>  e.g https://github.com/thoughtram/clog
  --setversion=<version>  e.g. 0.1.0
  --subtitle=<subtitle>   e.g. crazy-release-name
  --from=<from>           e.g. 12a8546
  --to=<to>               e.g. 8057684
  --from-latest-tag       uses the latest tag as starting point. Ignores other --from parameter")

fn main () {

    let start_nsec = get_time().nsec;
    let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

    let log_reader_config = LogReaderConfig {
        grep: "^feat|^fix|BREAKING'".to_string(),
        format: "%H%n%s%n%b%n==END==".to_string(),
        from: if args.flag_from_latest_tag { get_latest_tag() } else { args.flag_from },
        to: args.flag_to
    };

    let commits = get_commits(log_reader_config);

    let sections = build_sections(commits.clone());

    let contents = match File::open(&Path::new("changelog.md")).read_to_string() {
      Ok(content) => content,
      Err(_)      => "".to_string()
    };

    let mut file = File::open_mode(&Path::new("changelog.md"), Open, Write).ok().unwrap();
    let mut writer = LogWriter::new(&mut file, LogWriterOptions {
        repository_link: args.flag_repository,
        version: args.flag_setversion,
        subtitle: args.flag_subtitle
    });

    writer.write_header();
    writer.write_section("Bug Fixes", &sections.fixes);
    writer.write_section("Features", &sections.features);
    writer.write(contents.as_slice());

    let end_nsec = get_time().nsec;
    let elapsed_mssec = (end_nsec - start_nsec) / 1000000;
    println!("changelog updated. (took {} ms)", elapsed_mssec);
}
<|endoftext|>


<commit_before><commit_msg>fix newline parse error<commit_after><|endoftext|>


<commit_before><commit_msg>Push WIP wire protocol parser<commit_after>//! IRC wire protocol message parsers and generators. Incomplete; new messages are added as needed.
//!
//! Parsing and message generation are done directly on netbuf buffers to avoid redundant
//! allocations.

use netbuf::Buf;
use std::str;

/// <prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Pfx {
    Server(String),

    User {
        nick: String,
        /// user@host
        user: String,
    },
}

/// A PRIVMSG receiver.
pub enum Receiver {
    Chan(String),
    User(String)
}

pub enum Msg {
    PRIVMSG {
        // TODO: In theory this should be a list of receivers, but in prative I've never
        // encountered that case.
        receivers: Receiver,
        contents: String
    },

    JOIN {
        // TODO: Same as above, this should be a list ...
        chan: String
        // TODO: key field might be useful when joining restricted channels. In practice I've never
        // needed it.
    },

    PART {
        // TODO: List of channels
        chan: String
    },

    QUIT(String),

    NOTICE {
        nick: String,
        msg: String,
    },

    NICK(String),

    /// An IRC message other than the ones listed above.
    Other {
        cmd: String,
        params: Vec<String>
    },

    /// Numeric replies are kept generic as there are just too many replies and we probably only
    /// need to handle a small subset of them.
    Reply {
        num: u16,
        params: Vec<String>,
    }
}

/// An intermediate type used during parsing.
enum MsgType<'a> {
    Cmd(&'a str),
    Num(u16),
}

static CRLF: [u8; 2] = [b'\r', b'\n'];

impl Msg {
    /// Try to read an IRC message off a `netbuf` buffer. Drops the message when parsing is
    /// successful. Otherwise the buffer is left unchanged.
    pub fn read(buf: &mut Buf) -> Option<Msg> {
        // find "\r\n" separator. `IntoSearcher` implementation for slice needs `str` (why??) so
        // using this hacky method instead.
        let crlf_idx = {
            match buf.as_ref().windows(2).position(|sub| sub == CRLF) {
                None => return None,
                Some(i) => i,
            }
        };

        let ret = {
            let mut slice: &[u8] = &buf.as_ref()[ 0 .. crlf_idx ];

            let pfx: Option<Pfx> = {
                if slice[0] == b':' {
                    // parse prefix
                    let ws_idx = find_byte(slice, b' ').unwrap();
                    let (mut pfx, slice_) = slice.split_at(ws_idx);
                    // drop the : from pfx
                    pfx = &pfx[ 1 .. ];
                    slice = &slice_[ 1 .. ]; // drop the space
                    Some(parse_pfx(&pfx))
                } else {
                    None
                }
            };

            let msg_ty: MsgType = {
                let ws_idx = find_byte(slice, b' ').unwrap();
                let (cmd, slice_) = slice.split_at(ws_idx);
                slice = &slice_[ 1 .. ]; // drop the space
                match parse_reply_num(cmd) {
                    None => MsgType::Cmd(unsafe {
                        // Cmd strings are added by the server and they're always ASCII strings, so
                        // this is safe and O(1).
                        str::from_utf8_unchecked(cmd)
                    }),
                    Some(num) => MsgType::Num(num)
                }
            };

            let params = parse_params(slice);

            assert!(slice.is_empty());

            match msg_ty {
                MsgType::Cmd("PRIVMSG") if params.len() == 2 => {
                    // TODO
                },
                _ => {}
            }

            unimplemented!()
        };

        buf.consume(crlf_idx + 2);
        ret
    }
}

fn parse_pfx(pfx: &[u8]) -> Pfx {
    match find_byte(pfx, b'!') {
        None => Pfx::Server(unsafe { str::from_utf8_unchecked(pfx).to_owned() }),
        Some(idx) => {
            Pfx::User {
                nick: unsafe { str::from_utf8_unchecked(&pfx[ 0 .. idx ]) }.to_owned(),
                user: unsafe { str::from_utf8_unchecked(&pfx[ idx + 1 .. ]) }.to_owned()
            }
        }
    }
}

fn parse_reply_num(bs: &[u8]) -> Option<u16> {

    fn is_num_ascii(b : u8) -> bool {
        b >= b'0' && b <= b'9'
    }

    if bs.len() == 3 {
        let n3 = unsafe { *bs.get_unchecked(0) };
        let n2 = unsafe { *bs.get_unchecked(1) };
        let n1 = unsafe { *bs.get_unchecked(2) };
        if is_num_ascii(n3) && is_num_ascii(n2) && is_num_ascii(n1) {
            return Some(((n3 - b'0') as u16) * 100 +
                        ((n2 - b'0') as u16) * 10  +
                        ((n1 - b'0') as u16));
        }
    }
    None
}

fn parse_params(chrs : &[u8]) -> Vec<Vec<u8>> {
    let mut ret : Vec<Vec<u8>> = Vec::new();

    let mut current_param = Vec::new();
    for byte_idx in 0 .. chrs.len() {
        let byte = *unsafe { chrs.get_unchecked(byte_idx) };
        if byte == b':' {
            current_param.extend_from_slice(&chrs[ byte_idx + 1 .. ]);
            ret.push(current_param);
            return ret;
        } else if byte == b' ' {
            ret.push(current_param);
            current_param = Vec::new();
        } else {
            current_param.push(byte);
        }
    }

    if current_param.len() > 0 {
        ret.push(current_param);
    }

    ret
}

pub fn find_byte(buf: &[u8], byte0: u8) -> Option<usize> {
    for (byte_idx, byte) in buf.iter().enumerate() {
        if *byte == byte0 {
            return Some(byte_idx);
        }
    }
    None
}
<|endoftext|>


<commit_before><commit_msg>testsuite: Add xfailed test for #4335<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// xfail-test
fn id<T>(t: T) -> T { t }

fn f<T>(v: &r/T) -> &r/fn()->T { id::<&r/fn()->T>(|| *v) } //~ ERROR ???

fn main() {
    let v = &5;
    io::println(fmt!("%d", f(v)()));
}<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(const_int_ops)]
#![feature(test)]

extern crate test;
use test::black_box as b;

const BE_U32: u32 = 55u32.to_be();
const LE_U32: u32 = 55u32.to_le();
const BE_U128: u128 = 999999u128.to_be();
const LE_I128: i128 = -999999i128.to_le();

fn main() {
    assert_eq!(BE_U32, b(55u32).to_be());
    assert_eq!(LE_U32, b(55u32).to_le());
    assert_eq!(BE_U128, b(999999u128).to_be());
    assert_eq!(LE_I128, b(-999999i128).to_le());
}
<commit_msg>Ignore i128 test on asmjs<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(const_int_ops)]
#![feature(test)]

extern crate test;
use test::black_box as b;

const BE_U32: u32 = 55u32.to_be();
const LE_U32: u32 = 55u32.to_le();

fn main() {
    assert_eq!(BE_U32, b(55u32).to_be());
    assert_eq!(LE_U32, b(55u32).to_le());

    #[cfg(not(target_arch = "asmjs"))]
    {
        const BE_U128: u128 = 999999u128.to_be();
        const LE_I128: i128 = -999999i128.to_le();
        assert_eq!(BE_U128, b(999999u128).to_be());
        assert_eq!(LE_I128, b(-999999i128).to_le());
    }
}
<|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before><commit_msg>practice<commit_after>fn main() {
    let mut count = 0u32;
    println!("Let's count until infinity!");

    loop {
        count += 1;
        if count == 3 {
            println!("three");
            continue;
        }

        println!("{}", count);

        if count == 5 {
            println!("OK, that's enough");
            break;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>function pointer<commit_after>fn plus_one(i: i32) -> i32 {
    i + 1
}

fn main() {
    let f = plus_one;
    let six = f(5);
    println!("{}", six);
}
<|endoftext|>


<commit_before><commit_msg>tests/heap_allocations: init<commit_after>#![feature(custom_test_frameworks)]
#![no_main]
#![no_std]
#![reexport_test_harness_main = "test_main"]
#![test_runner(daedalos::test_runner)]

extern crate alloc;

use bootloader::{entry_point, BootInfo};
use core::panic::PanicInfo;
use daedalos::{serial_print, serial_println};

#[panic_handler]
fn panic(info: &PanicInfo) -> ! { daedalos::test_panic_handler(info) }

entry_point!(main);

fn main(boot_info: &'static BootInfo) -> ! {
    use daedalos::{
        allocator,
        memory::{self, BootInfoFrameAllocator},
    };
    use x86_64::VirtAddr;

    daedalos::init();
    let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
    let mut mapper = unsafe { memory::init(phys_mem_offset) };
    let mut frame_allocator = unsafe { BootInfoFrameAllocator::init(&boot_info.memory_map) };
    allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");

    test_main();
    loop {}
}

#[test_case]
fn simple_allocation() {
    use alloc::boxed::Box;
    serial_print!("simple_allocation... ");
    let heap_value = Box::new(41);
    assert_eq!(*heap_value, 41);
    serial_println!("[ok]");
}

#[test_case]
fn large_vec() {
    use alloc::vec::Vec;
    serial_print!("large_vec... ");
    let n = 1000;
    let mut vec = Vec::new();
    for i in 0..n {
        vec.push(i);
    }
    assert_eq!(vec.iter().sum::<u64>(), (n - 1) * n / 2);
    serial_println!("[ok]");
}

#[test_case]
fn many_boxes() {
    use alloc::boxed::Box;
    use daedalos::allocator::HEAP_SIZE;
    serial_print!("many_boxes... ");
    for i in 0..HEAP_SIZE {
        let x = Box::new(i);
        assert_eq!(*x, i);
    }
    serial_println!("[ok]");
}
<|endoftext|>


<commit_before><commit_msg>Added minimal example<commit_after>extern crate wlroots;

struct InputManager;
struct OutputManager;

impl wlroots::manager::OutputManagerHandler for OutputManager {}
impl wlroots::manager::InputManagerHandler for InputManager {}

fn main() {
    wlroots::compositor::Compositor::new(Box::new(InputManager), Box::new(OutputManager)).run()
}
<|endoftext|>


<commit_before><commit_msg>Problem 64<commit_after>enum BinaryTree<T> {
    Node(T, ~BinaryTree<T>, ~BinaryTree<T>),
    Empty
}

enum PosBinaryTree<T> {
    PosNode(T, (int, int), ~PosBinaryTree<T>, ~PosBinaryTree<T>),
    PosEmpty
}

impl<T: Eq> Eq for PosBinaryTree<T> {
    fn eq(&self, other: &PosBinaryTree<T>) -> bool {
        match (self, other) {
            (&PosEmpty, &PosEmpty) => true,
            (&PosNode(ref lv, ref posl, ~ref ll, ~ref lr),
             &PosNode(ref rv, ref posr, ~ref rl, ~ref rr)) => lv == rv &&
                                                              posl == posr &&
                                                              ll == rl &&
                                                              lr == rr,
            _ => false
        }
    }
}

fn layout_binary_tree<T: Clone>(tree: &BinaryTree<T>) -> PosBinaryTree<T> {
    fn aux<T: Clone>(leftmost: int, level: uint, subtree: &BinaryTree<T>) -> (int, PosBinaryTree<T>) {
        match subtree {
            &Empty => (leftmost, PosEmpty),
            &Node(ref e, ~ref l, ~ref r) => {
                let (middle, leftTree) = aux(leftmost, level + 1, l);
                let (rightmost, rightTree) = aux(middle + 1, level + 1, r);
                (rightmost, PosNode(e.clone(), (level as int, middle + 1), ~leftTree, ~rightTree))
            }
        }
    }
    let (_, r) = aux(0, 1, tree);
    r
}

fn main() {
    let tree = Node('n', ~Node('k', ~Node('c', ~Node('a', ~Empty,
                                                          ~Empty),
                                               ~Node('h', ~Node('g', ~Node('e', ~Empty,
                                                                                ~Empty),
                                                                     ~Empty),
                                                          ~Empty)),
                                    ~Node('m', ~Empty, ~Empty)),
                         ~Node('u', ~Node('p', ~Empty,
                                               ~Node('s', ~Node('q', ~Empty,
                                                                     ~Empty),
                                                          ~Empty)),
                                    ~Empty));
    let postree = PosNode('n', (1, 8), ~PosNode('k', (2, 6), ~PosNode('c',
        (3, 2), ~PosNode('a', (4, 1), ~PosEmpty, ~PosEmpty), ~PosNode('h',
        (4, 5), ~PosNode('g', (5, 4), ~PosNode('e', (6, 3), ~PosEmpty, ~PosEmpty),
        ~PosEmpty), ~PosEmpty)), ~PosNode('m', (3, 7), ~PosEmpty, ~PosEmpty)),
        ~PosNode('u', (2, 12), ~PosNode('p', (3, 9), ~PosEmpty, ~PosNode('s',
        (4, 11), ~PosNode('q', (5, 10), ~PosEmpty, ~PosEmpty), ~PosEmpty)), ~PosEmpty));

    assert!(layout_binary_tree(&tree) == postree);
}

<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(overloaded_calls, unboxed_closures)]

// Test by-ref capture of environment in unboxed closure types

fn call_fn<F: Fn()>(f: F) {
    f()
}

fn call_fn_mut<F: FnMut()>(mut f: F) {
    f()
}

fn call_fn_once<F: FnOnce()>(f: F) {
    f()
}

fn main() {
    let mut x = 0u;
    let y = 2u;

    call_fn(|&:| x += y);
    call_fn_mut(|&mut:| x += y);
    call_fn_once(|:| x += y);
    assert_eq!(x, y * 3);
}
<commit_msg>Fix unit test that was illegally mutating an upvar<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(overloaded_calls, unboxed_closures)]

// Test by-ref capture of environment in unboxed closure types

fn call_fn<F: Fn()>(f: F) {
    f()
}

fn call_fn_mut<F: FnMut()>(mut f: F) {
    f()
}

fn call_fn_once<F: FnOnce()>(f: F) {
    f()
}

fn main() {
    let mut x = 0u;
    let y = 2u;

    call_fn(|&:| assert_eq!(x, 0));
    call_fn_mut(|&mut:| x += y);
    call_fn_once(|:| x += y);
    assert_eq!(x, y * 2);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Traits for conversions between types.
//!
//! The traits in this module provide a general way to talk about conversions
//! from one type to another. They follow the standard Rust conventions of
//! `as`/`into`/`from`.
//!
//! Like many traits, these are often used as bounds for generic functions, to
//! support arguments of multiple types.
//!
//! - Impl the `As*` traits for reference-to-reference conversions
//! - Impl the `Into` trait when you want to consume the value in the conversion
//! - The `From` trait is the most flexible, useful for value _and_ reference conversions
//! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the
//!   conversion to fail
//!
//! As a library author, you should prefer implementing `From<T>` or `TryFrom<T>` rather than
//! `Into<U>` or `TryInto<U>`, as `From` and `TryFrom` provide greater flexibility and offer
//! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation
//! in the standard library.
//!
//! # Generic impl
//!
//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference
//! - `From<U> for T` implies `Into<T> for U`
//! - `TryFrom<U> for T` implies `TryInto<T> for U`
//! - `From` and `Into` are reflexive, which means that all types can `into()`
//!   themselves and `from()` themselves
//!
//! See each trait for usage examples.

#![stable(feature = "rust1", since = "1.0.0")]

/// A cheap, reference-to-reference conversion.
///
/// `AsRef` is very similar to, but different than, [`Borrow`]. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// Both [`String`] and `&str` implement `AsRef<str>`:
///
/// [`String`]: ../../std/string/struct.String.html
///
/// ```
/// fn is_hello<T: AsRef<str>>(s: T) {
///    assert_eq!("hello", s.as_ref());
/// }
///
/// let s = "hello";
/// is_hello(s);
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_ref(&self) -> &T;
}

/// A cheap, mutable reference-to-mutable reference conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// [`Box<T>`] implements `AsMut<T>`:
///
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
///
/// ```
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
///     *num.as_mut() += 1;
/// }
///
/// let mut boxed_num = Box::new(0);
/// add_one(&mut boxed_num);
/// assert_eq!(*boxed_num, 1);
/// ```
///
/// # Generic Impls
///
/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_mut(&mut self) -> &mut T;
}

/// A conversion that consumes `self`, which may or may not be expensive.
///
/// **Note: this trait must not fail**. If the conversion can fail, use [`TryInto`] or a dedicated
/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the [`From`][From] trait, which offers greater flexibility and provides an equivalent `Into`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// # Examples
///
/// [`String`] implements `Into<Vec<u8>>`:
///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
///    let bytes = b"hello".to_vec();
///    assert_eq!(bytes, s.into());
/// }
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - [`From<T>`][From]` for U` implies `Into<U> for T`
/// - [`into()`] is reflexive, which means that `Into<T> for T` is implemented
///
/// [`TryInto`]: trait.TryInto.html
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`String`]: ../../std/string/struct.String.html
/// [From]: trait.From.html
/// [`into()`]: trait.Into.html#tymethod.into
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into(self) -> T;
}

/// Construct `Self` via a conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use [`TryFrom`] or a dedicated
/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// # Examples
///
/// [`String`] implements `From<&str>`:
///
/// ```
/// let string = "hello".to_string();
/// let other_string = String::from("hello");
///
/// assert_eq!(string, other_string);
/// ```
/// # Generic impls
///
/// - `From<T> for U` implies [`Into<U>`]` for T`
/// - [`from()`] is reflexive, which means that `From<T> for T` is implemented
///
/// [`TryFrom`]: trait.TryFrom.html
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`String`]: ../../std/string/struct.String.html
/// [`Into<U>`]: trait.Into.html
/// [`from()`]: trait.From.html#tymethod.from
#[stable(feature = "rust1", since = "1.0.0")]
pub trait From<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from(T) -> Self;
}

/// An attempted conversion that consumes `self`, which may or may not be expensive.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the [`TryFrom`] trait, which offers greater flexibility and provides an equivalent `TryInto`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// [`TryFrom`]: trait.TryFrom.html
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryInto<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_into(self) -> Result<T, Self::Err>;
}

/// Attempt to construct `Self` via a conversion.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

////////////////////////////////////////////////////////////////////////////////
// GENERIC IMPLS
////////////////////////////////////////////////////////////////////////////////

// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
// // As lifts over Deref
// impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
//     fn as_ref(&self) -> &U {
//         self.deref().as_ref()
//     }
// }

// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
    fn as_mut(&mut self) -> &mut U {
        (*self).as_mut()
    }
}

// FIXME (#23442): replace the above impl for &mut with the following more general one:
// // AsMut lifts over DerefMut
// impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
//     fn as_mut(&mut self) -> &mut U {
//         self.deref_mut().as_mut()
//     }
// }

// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
    fn into(self) -> U {
        U::from(self)
    }
}

// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
    fn from(t: T) -> T { t }
}

// TryFrom implies TryInto
#[unstable(feature = "try_from", issue = "33417")]
impl<T, U> TryInto<U> for T where U: TryFrom<T> {
    type Err = U::Err;

    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

////////////////////////////////////////////////////////////////////////////////
// CONCRETE IMPLS
////////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
    fn as_ref(&self) -> &[T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}
<commit_msg>Auto merge of #39407 - GuillaumeGomez:convert_module, r=frewsxcv<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Traits for conversions between types.
//!
//! The traits in this module provide a general way to talk about conversions
//! from one type to another. They follow the standard Rust conventions of
//! `as`/`into`/`from`.
//!
//! Like many traits, these are often used as bounds for generic functions, to
//! support arguments of multiple types.
//!
//! - Impl the `As*` traits for reference-to-reference conversions
//! - Impl the [`Into`] trait when you want to consume the value in the conversion
//! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions
//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the
//!   conversion to fail
//!
//! As a library author, you should prefer implementing [`From<T>`][`From`] or
//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a blanket implementation
//! in the standard library.
//!
//! # Generic impl
//!
//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
//! - [`From`] and [`Into`] are reflexive, which means that all types can `into()`
//!   themselves and `from()` themselves
//!
//! See each trait for usage examples.
//!
//! [`Into`]: trait.Into.html
//! [`From`]: trait.From.html
//! [`TryFrom`]: trait.TryFrom.html
//! [`TryInto`]: trait.TryInto.html
//! [`AsRef`]: trait.AsRef.html
//! [`AsMut`]: trait.AsMut.html

#![stable(feature = "rust1", since = "1.0.0")]

/// A cheap, reference-to-reference conversion.
///
/// `AsRef` is very similar to, but different than, [`Borrow`]. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// Both [`String`] and `&str` implement `AsRef<str>`:
///
/// [`String`]: ../../std/string/struct.String.html
///
/// ```
/// fn is_hello<T: AsRef<str>>(s: T) {
///    assert_eq!("hello", s.as_ref());
/// }
///
/// let s = "hello";
/// is_hello(s);
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_ref(&self) -> &T;
}

/// A cheap, mutable reference-to-mutable reference conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which
/// returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// [`Box<T>`] implements `AsMut<T>`:
///
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
///
/// ```
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
///     *num.as_mut() += 1;
/// }
///
/// let mut boxed_num = Box::new(0);
/// add_one(&mut boxed_num);
/// assert_eq!(*boxed_num, 1);
/// ```
///
/// # Generic Impls
///
/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`)
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_mut(&mut self) -> &mut T;
}

/// A conversion that consumes `self`, which may or may not be expensive.
///
/// **Note: this trait must not fail**. If the conversion can fail, use [`TryInto`] or a dedicated
/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the [`From`][From] trait, which offers greater flexibility and provides an equivalent `Into`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// # Examples
///
/// [`String`] implements `Into<Vec<u8>>`:
///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
///    let bytes = b"hello".to_vec();
///    assert_eq!(bytes, s.into());
/// }
///
/// let s = "hello".to_string();
/// is_hello(s);
/// ```
///
/// # Generic Impls
///
/// - [`From<T>`][From]` for U` implies `Into<U> for T`
/// - [`into()`] is reflexive, which means that `Into<T> for T` is implemented
///
/// [`TryInto`]: trait.TryInto.html
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`String`]: ../../std/string/struct.String.html
/// [From]: trait.From.html
/// [`into()`]: trait.Into.html#tymethod.into
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn into(self) -> T;
}

/// Construct `Self` via a conversion.
///
/// **Note: this trait must not fail**. If the conversion can fail, use [`TryFrom`] or a dedicated
/// method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// # Examples
///
/// [`String`] implements `From<&str>`:
///
/// ```
/// let string = "hello".to_string();
/// let other_string = String::from("hello");
///
/// assert_eq!(string, other_string);
/// ```
/// # Generic impls
///
/// - `From<T> for U` implies [`Into<U>`]` for T`
/// - [`from()`] is reflexive, which means that `From<T> for T` is implemented
///
/// [`TryFrom`]: trait.TryFrom.html
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`String`]: ../../std/string/struct.String.html
/// [`Into<U>`]: trait.Into.html
/// [`from()`]: trait.From.html#tymethod.from
#[stable(feature = "rust1", since = "1.0.0")]
pub trait From<T>: Sized {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from(T) -> Self;
}

/// An attempted conversion that consumes `self`, which may or may not be expensive.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the [`TryFrom`] trait, which offers greater flexibility and provides an equivalent `TryInto`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// [`TryFrom`]: trait.TryFrom.html
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryInto<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_into(self) -> Result<T, Self::Err>;
}

/// Attempt to construct `Self` via a conversion.
#[unstable(feature = "try_from", issue = "33417")]
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

////////////////////////////////////////////////////////////////////////////////
// GENERIC IMPLS
////////////////////////////////////////////////////////////////////////////////

// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
// // As lifts over Deref
// impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
//     fn as_ref(&self) -> &U {
//         self.deref().as_ref()
//     }
// }

// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
    fn as_mut(&mut self) -> &mut U {
        (*self).as_mut()
    }
}

// FIXME (#23442): replace the above impl for &mut with the following more general one:
// // AsMut lifts over DerefMut
// impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
//     fn as_mut(&mut self) -> &mut U {
//         self.deref_mut().as_mut()
//     }
// }

// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
    fn into(self) -> U {
        U::from(self)
    }
}

// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
    fn from(t: T) -> T { t }
}

// TryFrom implies TryInto
#[unstable(feature = "try_from", issue = "33417")]
impl<T, U> TryInto<U> for T where U: TryFrom<T> {
    type Err = U::Err;

    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

////////////////////////////////////////////////////////////////////////////////
// CONCRETE IMPLS
////////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
    fn as_ref(&self) -> &[T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}
<|endoftext|>