<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |args: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        /// Simple command to create a file, in the current directory
        /// The file has got the name given as the first argument of the command
        /// If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "cfile",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => {
                        File::create(file_name);
                    }
                    None => {
                        println!("Could not create a file without a name");
                    }
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |args: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        err = true;
                    }
                } else {
                    err = true;
                }
                if err {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name) + " exit";

        commands.push(Command {
            name: "help",
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>Documentation typo has been modified<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |args: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "cfile",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => {
                        File::create(file_name);
                    }
                    None => {
                        println!("Could not create a file without a name");
                    }
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |args: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        err = true;
                    }
                } else {
                    err = true;
                }
                if err {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name) + " exit";

        commands.push(Command {
            name: "help",
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before>use parse::IrcMsg;

fn byte_length_sum(items: &[&str]) -> usize {
    let mut acc = 0;
    for len in items.iter().map(|x| x.as_bytes().len()) {
        acc += len;
    }
    acc
}

macro_rules! msg_wrapper_common {
    ($t:ident) => {
        impl $t {
            pub fn into_bytes(self) -> Vec<u8> {
                self.into_irc_msg().into_bytes()
            }

            pub fn into_irc_msg(self) -> IrcMsg {
                let $t(msg) = self;
                msg
            }

            pub fn to_irc_msg<'a>(&'a self) -> &'a IrcMsg {
                let $t(ref msg) = *self;
                msg
            }
        }
    }
}

#[derive(Clone, Debug)]
pub struct Join(IrcMsg);
msg_wrapper_common!(Join);

impl Join {
    pub fn new(channel: &str) -> Join {
        let output_length = byte_length_sum(&[channel]) + 5;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_with_key(channel: &str, key: &str) -> Join {
        let output_length = byte_length_sum(&[channel, key]) + 6;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());
        msg.push_all(b" ");
        msg.push_all(key.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Nick(IrcMsg);
msg_wrapper_common!(Nick);

impl Nick {
    pub fn new(argument: &str) -> Nick {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"NICK ");
        msg.push_all(argument.as_bytes());
        Nick(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Ping(IrcMsg);
msg_wrapper_common!(Ping);

impl Ping {
    pub fn new(argument: &str) -> Ping {
        let mut msg = Vec::with_capacity(6 + argument.as_bytes().len());
        msg.push_all(b"PING :");
        msg.push_all(argument.as_bytes());
        Ping(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Pong(IrcMsg);
msg_wrapper_common!(Pong);

impl Pong {
    pub fn new(argument: &str) -> Pong {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"PONG ");
        msg.push_all(argument.as_bytes());
        Pong(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Privmsg(IrcMsg);
msg_wrapper_common!(Privmsg);

impl Privmsg {
    pub fn new(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" :");
        msg.push_all(argument);

        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_ctcp(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" \x01");
        msg.push_all(argument);
        msg.push_all(b"\x01");
        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct User(IrcMsg);
msg_wrapper_common!(User);

impl User {
    //  <user> <mode> <unused> <realname>
    pub fn new(user: &str, mode: &str, unused: &str, realname: &str) -> User {

        let output_length = byte_length_sum(&[user, mode, unused, realname]) + 8;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"USER ");
        msg.push_all(user.as_bytes());
        msg.push_all(b" ");
        msg.push_all(mode.as_bytes());
        msg.push_all(b" ");
        msg.push_all(unused.as_bytes());
        msg.push_all(b" :");
        msg.push_all(realname.as_bytes());

        User(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Who(IrcMsg);
msg_wrapper_common!(Who);

impl Who {
    pub fn new(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_opers(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" o");

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}
<commit_msg>Add client::Quit<commit_after>use parse::IrcMsg;

fn byte_length_sum(items: &[&str]) -> usize {
    let mut acc = 0;
    for len in items.iter().map(|x| x.as_bytes().len()) {
        acc += len;
    }
    acc
}

macro_rules! msg_wrapper_common {
    ($t:ident) => {
        impl $t {
            pub fn into_bytes(self) -> Vec<u8> {
                self.into_irc_msg().into_bytes()
            }

            pub fn into_irc_msg(self) -> IrcMsg {
                let $t(msg) = self;
                msg
            }

            pub fn to_irc_msg<'a>(&'a self) -> &'a IrcMsg {
                let $t(ref msg) = *self;
                msg
            }
        }
    }
}

#[derive(Clone, Debug)]
pub struct Join(IrcMsg);
msg_wrapper_common!(Join);

impl Join {
    pub fn new(channel: &str) -> Join {
        let output_length = byte_length_sum(&[channel]) + 5;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_with_key(channel: &str, key: &str) -> Join {
        let output_length = byte_length_sum(&[channel, key]) + 6;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());
        msg.push_all(b" ");
        msg.push_all(key.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Nick(IrcMsg);
msg_wrapper_common!(Nick);

impl Nick {
    pub fn new(argument: &str) -> Nick {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"NICK ");
        msg.push_all(argument.as_bytes());
        Nick(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Ping(IrcMsg);
msg_wrapper_common!(Ping);

impl Ping {
    pub fn new(argument: &str) -> Ping {
        let mut msg = Vec::with_capacity(6 + argument.as_bytes().len());
        msg.push_all(b"PING :");
        msg.push_all(argument.as_bytes());
        Ping(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Pong(IrcMsg);
msg_wrapper_common!(Pong);

impl Pong {
    pub fn new(argument: &str) -> Pong {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"PONG ");
        msg.push_all(argument.as_bytes());
        Pong(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Privmsg(IrcMsg);
msg_wrapper_common!(Privmsg);

impl Privmsg {
    pub fn new(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" :");
        msg.push_all(argument);

        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_ctcp(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" \x01");
        msg.push_all(argument);
        msg.push_all(b"\x01");
        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct User(IrcMsg);
msg_wrapper_common!(User);

impl User {
    //  <user> <mode> <unused> <realname>
    pub fn new(user: &str, mode: &str, unused: &str, realname: &str) -> User {

        let output_length = byte_length_sum(&[user, mode, unused, realname]) + 8;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"USER ");
        msg.push_all(user.as_bytes());
        msg.push_all(b" ");
        msg.push_all(mode.as_bytes());
        msg.push_all(b" ");
        msg.push_all(unused.as_bytes());
        msg.push_all(b" :");
        msg.push_all(realname.as_bytes());

        User(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Who(IrcMsg);
msg_wrapper_common!(Who);

impl Who {
    pub fn new(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_opers(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" o");

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Debug)]
pub struct Quit(IrcMsg);
msg_wrapper_common!(Quit);

impl Quit {
    pub fn new(target: &str) -> Quit {
        let mut msg = Vec::new();
        msg.push_all(b"QUIT :");
        msg.push_all(target.as_bytes());

        Quit(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}
<|endoftext|>


<commit_before>//! Parses textual IL as emited by [`ir_writer`](::middle::ir_writer).

mod parser_util;
mod parser;
mod lowering;
mod simple_ast;

use middle::ssa::ssastorage::SSAStorage;

/// Parses textual IL as emited by [`ir_writer`](::middle::ir_writer).
/// The returned SSA is empty if an error occured.
pub fn parse_il<T: AsRef<str>>(il: T) -> SSAStorage {
    let mut ret = SSAStorage::new();
    match parser::parse_Function(il.as_ref()) {
        Ok(sast) => lowering::lower_simpleast(&mut ret, sast)
            .unwrap_or_else(|e| radeco_err!("Error lowering AST to SSA: {:?}", e)),
        Err(s) => radeco_err!("Error parsing IL: {}", s),
    }
    ret
}

#[cfg(test)]
mod test {
    use middle::ir_writer::IRWriter;
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;

    const SSA_TXT: &str = r#"
define-fun main(unknown) -> unknown {
    registers: $r15,$r14,$r13,$r12,$rbp,$rbx,$r11,$r10,$r9,$r8,$rax,$rcx,$rdx,$rsi,$rdi,$rip,$cs,$cf,$pf,$af,$zf,$sf,$tf,$if,$df,$of,$rsp,$ss,$fs_base,$gs_base,$ds,$es,$fs,$gs;
    bb_0x0005FA.0000():
        [@0x0005FA.0001] %1: $Unknown64(*?) = {rsi} + #x1;
    exit-node:
    final-register-state:
        $rax = %1;
}"#;

    #[test]
    fn check_ssa_parse() {
        use middle::ir::MOpcode::*;
        use middle::ir::WidthSpec;
        use middle::ssa::cfg_traits::*;
        use middle::ssa::ssa_traits::*;
        use middle::ssa::ssastorage::NodeData;
        use middle::ssa::ssastorage::SSAStorage;
        use std::collections::HashSet;

        let ssa = super::parse_il(SSA_TXT);

        let entry = ssa.entry_node().unwrap();
        let succs = ssa.succs_of(entry);
        assert_eq!(succs.len(), 1);
        let real_entry = succs[0];
        let exprs = ssa.exprs_in(real_entry).into_iter().collect::<HashSet<_>>();
        let exit = ssa.exit_node().unwrap();
        let frs_node = ssa.registers_in(exit).unwrap();
        let frs = ssa.operands_of(frs_node);

        let rbp_i = ssa.regnames.iter().position(|r| r == "rax").unwrap();
        let v1 = frs[rbp_i];
        assert!(exprs.contains(&v1));
        assert_eq!(
            ssa.g[v1],
            NodeData::Op(OpAdd, ValueInfo::new_unresolved(WidthSpec::new_known(64)))
        );
        let v1_ops = ssa.operands_of(v1);
        assert_eq!(v1_ops.len(), 2);
        let cmt_rsi = v1_ops[0];
        assert_eq!(
            ssa.g[cmt_rsi],
            NodeData::Comment(
                ValueInfo::new_unresolved(WidthSpec::Unknown),
                "rsi".to_owned()
            )
        );
        let x1 = v1_ops[1];
        assert_eq!(
            ssa.g[x1],
            NodeData::Op(OpConst(1), ValueInfo::new_scalar(WidthSpec::new_known(64)))
        );
    }

    #[test]
    fn roundtrip_basic_ssa() {
        roundtrip("main".to_owned(), SSA_TXT);
    }

    #[test]
    fn roundtrip_bin1_main() {
        roundtrip_file("main".to_owned(), "test_files/bin1_main_ssa");
    }

    fn roundtrip_file<P: AsRef<Path>>(fn_name: String, file_path: P) {
        let ssa_txt = {
            let mut ssa_txt_file = File::open(file_path).expect("Error opening file");
            let mut contents = String::new();
            ssa_txt_file
                .read_to_string(&mut contents)
                .expect("Error reading file");
            contents
        };
        roundtrip(fn_name, &ssa_txt);
    }

    fn roundtrip(fn_name: String, ssa_txt: &str) {
        let parsed = super::parse_il(ssa_txt);
        let emited = IRWriter::default().emit_il(Some(fn_name), &parsed);
        assert_eq!(ssa_txt, emited);
    }
}
<commit_msg>Fix `ir_reader` test<commit_after>//! Parses textual IL as emited by [`ir_writer`](::middle::ir_writer).

mod parser_util;
mod parser;
mod lowering;
mod simple_ast;

use middle::ssa::ssastorage::SSAStorage;

/// Parses textual IL as emited by [`ir_writer`](::middle::ir_writer).
/// The returned SSA is empty if an error occured.
pub fn parse_il<T: AsRef<str>>(il: T) -> SSAStorage {
    let mut ret = SSAStorage::new();
    match parser::parse_Function(il.as_ref()) {
        Ok(sast) => lowering::lower_simpleast(&mut ret, sast)
            .unwrap_or_else(|e| radeco_err!("Error lowering AST to SSA: {:?}", e)),
        Err(s) => radeco_err!("Error parsing IL: {}", s),
    }
    ret
}

#[cfg(test)]
mod test {
    use middle::ir_writer::IRWriter;
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;

    const SSA_TXT: &str = r#"
define-fun main(unknown) -> unknown {
    registers: $r15,$r14,$r13,$r12,$rbp,$rbx,$r11,$r10,$r9,$r8,$rax,$rcx,$rdx,$rsi,$rdi,$rip,$cs,$cf,$pf,$af,$zf,$sf,$tf,$if,$df,$of,$rsp,$ss,$fs_base,$gs_base,$ds,$es,$fs,$gs;
    bb_0x0005FA.0000():
        [@0x0005FA.0001] %1: $Unknown64(*?) = {rsi} + #x1;
    exit-node:
    final-register-state:
        $r15 = {r15};
        $r14 = {r14};
        $r13 = {r13};
        $r12 = {r12};
        $rbp = {rbp};
        $rbx = {rbx};
        $r11 = {r11};
        $r10 = {r10};
        $r9 = {r9};
        $r8 = {r8};
        $rax = %1;
        $rcx = {rcx};
        $rdx = {rdx};
        $rsi = {rsi};
        $rdi = {rdi};
        $rip = {rip};
        $cs = {cs};
        $cf = {cf};
        $pf = {pf};
        $af = {af};
        $zf = {zf};
        $sf = {sf};
        $tf = {tf};
        $if = {if};
        $df = {df};
        $of = {of};
        $rsp = {rsp};
        $ss = {ss};
        $fs_base = {fs_base};
        $gs_base = {gs_base};
        $ds = {ds};
        $es = {es};
        $fs = {fs};
        $gs = {gs};
        $mem = {mem};
}"#;

    #[test]
    fn check_ssa_parse() {
        use middle::ir::MOpcode::*;
        use middle::ir::WidthSpec;
        use middle::ssa::cfg_traits::*;
        use middle::ssa::ssa_traits::*;
        use middle::ssa::ssastorage::NodeData;
        use middle::ssa::ssastorage::SSAStorage;
        use std::collections::HashSet;

        let ssa = super::parse_il(SSA_TXT);

        let entry = ssa.entry_node().unwrap();
        let succs = ssa.succs_of(entry);
        assert_eq!(succs.len(), 1);
        let real_entry = succs[0];
        let exprs = ssa.exprs_in(real_entry).into_iter().collect::<HashSet<_>>();
        let exit = ssa.exit_node().unwrap();
        let frs_node = ssa.registers_in(exit).unwrap();
        let frs = ssa.operands_of(frs_node);

        let rbp_i = ssa.regnames.iter().position(|r| r == "rax").unwrap();
        let v1 = frs[rbp_i];
        assert!(exprs.contains(&v1));
        assert_eq!(
            ssa.g[v1],
            NodeData::Op(OpAdd, ValueInfo::new_unresolved(WidthSpec::new_known(64)))
        );
        let v1_ops = ssa.operands_of(v1);
        assert_eq!(v1_ops.len(), 2);
        let cmt_rsi = v1_ops[0];
        assert_eq!(
            ssa.g[cmt_rsi],
            NodeData::Comment(
                ValueInfo::new_unresolved(WidthSpec::Unknown),
                "rsi".to_owned()
            )
        );
        let x1 = v1_ops[1];
        assert_eq!(
            ssa.g[x1],
            NodeData::Op(OpConst(1), ValueInfo::new_scalar(WidthSpec::new_known(64)))
        );
    }

    #[test]
    fn roundtrip_basic_ssa() {
        roundtrip("main".to_owned(), SSA_TXT);
    }

    #[test]
    fn roundtrip_bin1_main() {
        roundtrip_file("main".to_owned(), "test_files/bin1_main_ssa");
    }

    fn roundtrip_file<P: AsRef<Path>>(fn_name: String, file_path: P) {
        let ssa_txt = {
            let mut ssa_txt_file = File::open(file_path).expect("Error opening file");
            let mut contents = String::new();
            ssa_txt_file
                .read_to_string(&mut contents)
                .expect("Error reading file");
            contents
        };
        roundtrip(fn_name, &ssa_txt);
    }

    fn roundtrip(fn_name: String, ssa_txt: &str) {
        let parsed = super::parse_il(ssa_txt);
        let emited = IRWriter::default().emit_il(Some(fn_name), &parsed);
        assert_eq!(ssa_txt, emited);
    }
}
<|endoftext|>


<commit_before>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
#[derive(PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self) {
        // TODO theta = 60degrees use 3/4th and 1/4th

        let detector = Particle::get_detector_direction();
        let rnd = random::<f32>();

        self.spin = match detector {
            Detector::D12 => SpinDown,
            Detector::D3 => match rnd {
                0.0  ... 0.33 => SpinUp,
                0.33 ... 1.00 => SpinDown,
                _ => unreachable!()
            },
            Detector::D9 => match rnd {
                0.0  ... 0.33 => SpinDown,
                0.33 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        self.measure();
        friend.spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {
        let rnd = random::<f32>();

        let detector = match rnd {
            0.0  ... 0.33 => Detector::D12,
            0.33 ... 0.66 => Detector::D3,
            0.66 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let mut particle = Particle{spin: SpinSuper};
    particle.measure();
    println!("particle {}", particle.spin);

    let mut trials: f64 = 1000f64;
    let mut num_different: f64 = 0f64;

    let particles = Particle::new_pair();
    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");

    trials = 1000f64;
    num_different = 0f64;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;
        lhs.hidden_information(&mut rhs, OddBall);

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("         Should be about 5/9th or {}%", 100.0 * 5.0/9.0);

}
<commit_msg>getting spookier<commit_after>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
#[derive(PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
#[derive(PartialEq)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, detector: &Detector) {
        self.spin = match detector {
            &Detector::D12 => SpinUp,
            &Detector::D3 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
            &Detector::D9 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let detector1 = Detector::D12; //Particle::get_detector_direction();
        let detector2 = Particle::get_detector_direction();

        self.measure (&detector1);

        if detector1 == detector2 { // 1/3
            friend.spin = match self.spin {
                SpinUp => SpinDown,
                SpinDown => SpinUp,
                _ => unreachable!()
            };
        } else { // 2/3
            friend.measure(&detector2);
        }

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {
        let rnd = random::<f32>();

        let detector = match rnd {
            0.0  ... 0.33 => Detector::D12,
            0.33 ... 0.66 => Detector::D3,
            0.66 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let mut trials: f64 = 1000000f64;
    let mut num_different: f64 = 0f64;

    let particles = Particle::new_pair();
    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");

    num_different = 0f64;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        if random::<f32>() < 0.50 {
            lhs.hidden_information(&mut rhs, OddBall);
        } else {
            lhs.hidden_information(&mut rhs, Trivial);
        }

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("  Should be greater than 5/9th or {}%", 100.0 * 5.0/9.0);

}
<|endoftext|>


<commit_before>//! TODO Fill in

use nix::{self, libc};
use render;
use gdk_pixbuf::Pixbuf;
use glib::translate::ToGlibPtr;
use std::fmt::{self, Display, Formatter};
use std::process::{Command, Stdio};
use std::thread;
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::signal;

#[derive(Clone, Debug)]
pub struct AwesomeState {
    preferred_icon_size: u32
}

impl Default for AwesomeState {
    fn default() -> Self {
        AwesomeState {
            preferred_icon_size: 0
        }
    }
}

impl Display for AwesomeState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Awesome: {:p}", self)
    }
}

impl UserData for AwesomeState {}

pub fn init(lua: &Lua) -> rlua::Result<()> {
    let awesome_table = lua.create_table();
    state_setup(lua, &awesome_table)?;
    meta_setup(lua, &awesome_table)?;
    method_setup(lua, &awesome_table)?;
    property_setup(lua, &awesome_table)?;
    let globals = lua.globals();
    globals.set("awesome", awesome_table)
}

fn state_setup(lua: &Lua, awesome_table: &Table) -> rlua::Result<()> {
    awesome_table.set("__data", AwesomeState::default().to_lua(lua)?)
}

fn meta_setup(lua: &Lua, awesome_table: &Table) -> rlua::Result<()> {
    let meta_table = awesome_table.get_metatable().unwrap_or_else(|| {
        let table = lua.create_table();
        awesome_table.set_metatable(Some(table.clone()));
        table
    });
    meta_table.set("__tostring", lua.create_function(|_, val: Table| {
        Ok(format!("{}", val.get::<_, AwesomeState>("__data")?))
    }))
}

fn method_setup<'lua>(lua: &'lua Lua, awesome_table: &Table<'lua>) -> rlua::Result<()> {
    // TODO Fill in rest
    awesome_table.set("connect_signal", lua.create_function(signal::global_connect_signal))?;
    awesome_table.set("disconnect_signal", lua.create_function(signal::global_disconnect_signal))?;
    awesome_table.set("emit_signal", lua.create_function(signal::global_emit_signal))?;
    awesome_table.set("xrdb_get_value", lua.create_function(xrdb_get_value))?;
    awesome_table.set("xkb_set_layout_group", lua.create_function(xkb_set_layout_group))?;
    awesome_table.set("xkb_get_layout_group", lua.create_function(xkb_get_layout_group))?;
    awesome_table.set("set_preferred_icon_size", lua.create_function(set_preferred_icon_size))?;
    awesome_table.set("register_xproperty", lua.create_function(register_xproperty))?;
    awesome_table.set("xkb_get_group_names", lua.create_function(xkb_get_group_names))?;
    awesome_table.set("set_xproperty", lua.create_function(set_xproperty))?;
    awesome_table.set("get_xproperty", lua.create_function(get_xproperty))?;
    awesome_table.set("restart", lua.create_function(restart))?;
    awesome_table.set("load_image", lua.create_function(load_image))?;
    awesome_table.set("sync", lua.create_function(sync))?;
    awesome_table.set("exec", lua.create_function(exec))?;
    awesome_table.set("kill", lua.create_function(kill))?;
    awesome_table.set("quit", lua.create_function(quit))
}

fn property_setup<'lua>(lua: &'lua Lua, awesome_table: &Table<'lua>) -> rlua::Result<()> {
    // TODO Do properly
    awesome_table.set("version", "0".to_lua(lua)?)?;
    awesome_table.set("themes_path", "/usr/share/awesome/themes".to_lua(lua)?)?;
    awesome_table.set("conffile", "".to_lua(lua)?)
}

/// Registers a new X property
/// This actually does nothing, since this is Wayland.
fn register_xproperty<'lua>(_: &'lua Lua, _: Value<'lua>) -> rlua::Result<()> {
    warn!("register_xproperty not supported");
    Ok(())
}

/// Get layout short names
fn xkb_get_group_names<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<String> {
    use xcb::{xkb, Connection};
    use std::os::unix::io::AsRawFd;
    // TODO Init somewhere else
    let con = Connection::connect(None/*Some("wayland-0")*/).unwrap().0;
    // Tell xcb we are using the xkb extension
    {
        let cookie = xkb::use_extension(&con, 1, 0);

        match cookie.get_reply() {
            Ok(r) => {
                if !r.supported() {
                    panic!("xkb-1.0 is not supported");
                }
            },
            Err(_) => {
                panic!("could not get xkb extension supported version");
            }
        };
    }
    let id = xkb::ID_USE_CORE_KBD as _;
    let names_cookie = xkb::get_names_unchecked(&con, id, xkb::NAME_DETAIL_SYMBOLS);
    let names_r = names_cookie.get_reply().unwrap();
    /*use std::process::{Stdio, Command};
    // TODO FIXME wow this is _really_ _really_ dumb.
    // like really dumb
    // but not sure how else to do this to communicate to xwayland...
    warn!("xkb_get_group_names not supported");
    warn!("Doing a bad hack now");
    warn!("Fix me before release!");
    // This should be a function, not a whole freaking command!
    Ok(Command::new("/usr/bin/setxkbmap").arg("-v").arg("-query")
        .stdout(Stdio::piped())
        .spawn()
        .map(|child| {
            child.wait_with_output().ok().and_then(|output| {
                let stdout = String::from_utf8(output.stdout)
                    .expect("Output was not utf8");
                for line in stdout.lines() {
                    if line.contains("symbols:") {
                        let last = line.split(" ").last().unwrap();
                        return Some(last.trim().into())
                    }
                }
                None
            })
        }).unwrap_or_else(|err| {
            warn!("err: {:#?}", err);
            Some("pc+us+inet(evdev)".into())
        }).unwrap())
        */
    Ok("pc+us+inet(evdev)".into())
}

/// Restart Awesome by restarting the Lua thread
fn restart<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    use lua::{self, LuaQuery};
    if let Err(err) = lua::send(LuaQuery::Restart) {
        warn!("Could not restart Lua thread {:#?}", err);
    }
    Ok(())
}

/// Load an image from the given path
/// Returns either a cairo surface as light user data, nil and an error message
fn load_image<'lua>(lua: &'lua Lua, file_path: String) -> rlua::Result<Value<'lua>> {
    let pixbuf = Pixbuf::new_from_file(file_path.as_str())
        .map_err(|err| rlua::Error::RuntimeError(format!("{}", err)))?;
    let surface = render::load_surface_from_pixbuf(pixbuf);
    // UGH, I wanted to do to_glib_full, but that isn't defined apparently
    // So now I have to ignore the lifetime completely and just forget about the surface.
    let surface_ptr = surface.to_glib_none().0;
    ::std::mem::forget(surface);
    rlua::LightUserData(surface_ptr as _).to_lua(lua)
}

fn exec(_: &Lua, command: String) -> rlua::Result<()> {
    trace!("exec: \"{}\"", command);
    thread::Builder::new().name(command.clone()).spawn(|| {
        Command::new(command)
            .stdout(Stdio::null())
            .spawn()
            .expect("Could not spawn command")
    }).expect("Unable to spawn thread");
    Ok(())
}

/// Kills a PID with the given signal
///
/// Returns false if it could not send the signal to that process
fn kill(_: &Lua, (pid, sig): (libc::pid_t, libc::c_int)) -> rlua::Result<bool> {
    Ok(nix::sys::signal::kill(pid, sig).is_ok())
}

fn set_preferred_icon_size(lua: &Lua, val: u32) -> rlua::Result<()> {
    let mut awesome_state: AwesomeState = lua.globals().get::<_, Table>("awesome")?.get("__data")?;
    awesome_state.preferred_icon_size = val;
    lua.globals().get::<_, Table>("awesome")?.set("__data", awesome_state.to_lua(lua)?)

}

fn quit(_: &Lua, _: ()) -> rlua::Result<()> {
    ::rustwlc::terminate();
    Ok(())
}

/// No need to sync in Wayland
fn sync(_: &Lua, _: ()) -> rlua::Result<()> { Ok(()) }

fn set_xproperty(_: &Lua, _: Value) -> rlua::Result<()> {
    warn!("set_xproperty not supported");
    Ok(())
}

fn get_xproperty(_: &Lua, _: Value) -> rlua::Result<()> {
    warn!("get_xproperty not supported");
    Ok(())
}

fn xkb_set_layout_group(_: &Lua, _group: i32) -> rlua::Result<()> {
    warn!("xkb_set_layout_group not supported; Wait until wlroots");
    Ok(())
}

fn xkb_get_layout_group(_: &Lua, _: ()) -> rlua::Result<i32> {
    warn!("xkb_get_layout_group not supported; Wait until wlroots");
    warn!("Returning dummy data so I can move forward");
    warn!("Replace me before release!");
    Ok(0)
}

fn xrdb_get_value(lua: &Lua, (_resource_class, resource_name): (String, String))
                  -> rlua::Result<Value> {
    if &resource_name == "Xft.dpi" {
        return Ok("1".to_lua(lua)?)
    }
    warn!("xrdb_get_value not supported");
    Ok(Value::Nil)
}
<commit_msg>Implement xkb_get_group_names properly<commit_after>//! TODO Fill in

use xcb::{xkb, ffi, xproto, Connection};
use std::os::unix::io::AsRawFd;
use nix::{self, libc};
use render;
use gdk_pixbuf::Pixbuf;
use glib::translate::ToGlibPtr;
use std::fmt::{self, Display, Formatter};
use std::process::{Command, Stdio};
use std::thread;
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::signal;

// TODO this isn't defined in the xcb crate, even though it should be.
// A patch should be open adding this to its generation scheme
extern "C" {
    fn xcb_xkb_get_names_value_list_unpack(buffer: *mut libc::c_void,
                                           nTypes: u8,
                                           indicators: u32,
                                           virtualMods: u16,
                                           groupNames: u8,
                                           nKeys: u8,
                                           nKeyAliases: u8,
                                           nRadioGroups: u8,
                                           which: u32,
                                           aux: *mut ffi::xkb::xcb_xkb_get_names_value_list_t) -> libc::c_int;
}

#[derive(Clone, Debug)]
pub struct AwesomeState {
    preferred_icon_size: u32
}

impl Default for AwesomeState {
    fn default() -> Self {
        AwesomeState {
            preferred_icon_size: 0
        }
    }
}

impl Display for AwesomeState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Awesome: {:p}", self)
    }
}

impl UserData for AwesomeState {}

pub fn init(lua: &Lua) -> rlua::Result<()> {
    let awesome_table = lua.create_table();
    state_setup(lua, &awesome_table)?;
    meta_setup(lua, &awesome_table)?;
    method_setup(lua, &awesome_table)?;
    property_setup(lua, &awesome_table)?;
    let globals = lua.globals();
    globals.set("awesome", awesome_table)
}

fn state_setup(lua: &Lua, awesome_table: &Table) -> rlua::Result<()> {
    awesome_table.set("__data", AwesomeState::default().to_lua(lua)?)
}

fn meta_setup(lua: &Lua, awesome_table: &Table) -> rlua::Result<()> {
    let meta_table = awesome_table.get_metatable().unwrap_or_else(|| {
        let table = lua.create_table();
        awesome_table.set_metatable(Some(table.clone()));
        table
    });
    meta_table.set("__tostring", lua.create_function(|_, val: Table| {
        Ok(format!("{}", val.get::<_, AwesomeState>("__data")?))
    }))
}

fn method_setup<'lua>(lua: &'lua Lua, awesome_table: &Table<'lua>) -> rlua::Result<()> {
    // TODO Fill in rest
    awesome_table.set("connect_signal", lua.create_function(signal::global_connect_signal))?;
    awesome_table.set("disconnect_signal", lua.create_function(signal::global_disconnect_signal))?;
    awesome_table.set("emit_signal", lua.create_function(signal::global_emit_signal))?;
    awesome_table.set("xrdb_get_value", lua.create_function(xrdb_get_value))?;
    awesome_table.set("xkb_set_layout_group", lua.create_function(xkb_set_layout_group))?;
    awesome_table.set("xkb_get_layout_group", lua.create_function(xkb_get_layout_group))?;
    awesome_table.set("set_preferred_icon_size", lua.create_function(set_preferred_icon_size))?;
    awesome_table.set("register_xproperty", lua.create_function(register_xproperty))?;
    awesome_table.set("xkb_get_group_names", lua.create_function(xkb_get_group_names))?;
    awesome_table.set("set_xproperty", lua.create_function(set_xproperty))?;
    awesome_table.set("get_xproperty", lua.create_function(get_xproperty))?;
    awesome_table.set("restart", lua.create_function(restart))?;
    awesome_table.set("load_image", lua.create_function(load_image))?;
    awesome_table.set("sync", lua.create_function(sync))?;
    awesome_table.set("exec", lua.create_function(exec))?;
    awesome_table.set("kill", lua.create_function(kill))?;
    awesome_table.set("quit", lua.create_function(quit))
}

fn property_setup<'lua>(lua: &'lua Lua, awesome_table: &Table<'lua>) -> rlua::Result<()> {
    // TODO Do properly
    awesome_table.set("version", "0".to_lua(lua)?)?;
    awesome_table.set("themes_path", "/usr/share/awesome/themes".to_lua(lua)?)?;
    awesome_table.set("conffile", "".to_lua(lua)?)
}

/// Registers a new X property
/// This actually does nothing, since this is Wayland.
fn register_xproperty<'lua>(_: &'lua Lua, _: Value<'lua>) -> rlua::Result<()> {
    warn!("register_xproperty not supported");
    Ok(())
}

/// Get layout short names
fn xkb_get_group_names<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<String> {
    // TODO Init somewhere else
    let con = Connection::connect(None/*Some("wayland-0")*/).unwrap().0;
    // Tell xcb we are using the xkb extension
    {
        let cookie = xkb::use_extension(&con, 1, 0);

        match cookie.get_reply() {
            Ok(r) => {
                if !r.supported() {
                    panic!("xkb-1.0 is not supported");
                }
            },
            Err(_) => {
                panic!("could not get xkb extension supported version");
            }
        };
    }
    let id = xkb::ID_USE_CORE_KBD as _;
    let names_cookie = xkb::get_names_unchecked(&con, id, xkb::NAME_DETAIL_SYMBOLS);
    let names_r = names_cookie.get_reply().unwrap();
    // FIXME
    // hmm surely we can do this safely
    let name = unsafe {
        let buffer = ffi::xkb::xcb_xkb_get_names_value_list(names_r.ptr);
        let mut names_list: ffi::xkb::xcb_xkb_get_names_value_list_t = ::std::mem::uninitialized();
        let names_r_ptr = names_r.ptr;
        xcb_xkb_get_names_value_list_unpack(buffer, (*names_r_ptr).nTypes, (*names_r_ptr).indicators, (*names_r_ptr).virtualMods,
                                            (*names_r_ptr).groupNames, (*names_r_ptr).nKeys, (*names_r_ptr).nKeyAliases,
                                            (*names_r_ptr).nRadioGroups, (*names_r_ptr).which, &mut names_list);
        let atom_name_c = ffi::xproto::xcb_get_atom_name_unchecked(con.get_raw_conn(), names_list.symbolsName);
        let atom_name_r = ffi::xproto::xcb_get_atom_name_reply(con.get_raw_conn(), atom_name_c, ::std::ptr::null_mut());
        let name_c = ffi::xproto::xcb_get_atom_name_name(atom_name_r);
        ::std::ffi::CStr::from_ptr(name_c).to_string_lossy().into_owned()
    };
    error!("name: {}", name);
    return Ok(name)
}

/// Restart Awesome by restarting the Lua thread
fn restart<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    use lua::{self, LuaQuery};
    if let Err(err) = lua::send(LuaQuery::Restart) {
        warn!("Could not restart Lua thread {:#?}", err);
    }
    Ok(())
}

/// Load an image from the given path
/// Returns either a cairo surface as light user data, nil and an error message
fn load_image<'lua>(lua: &'lua Lua, file_path: String) -> rlua::Result<Value<'lua>> {
    let pixbuf = Pixbuf::new_from_file(file_path.as_str())
        .map_err(|err| rlua::Error::RuntimeError(format!("{}", err)))?;
    let surface = render::load_surface_from_pixbuf(pixbuf);
    // UGH, I wanted to do to_glib_full, but that isn't defined apparently
    // So now I have to ignore the lifetime completely and just forget about the surface.
    let surface_ptr = surface.to_glib_none().0;
    ::std::mem::forget(surface);
    rlua::LightUserData(surface_ptr as _).to_lua(lua)
}

fn exec(_: &Lua, command: String) -> rlua::Result<()> {
    trace!("exec: \"{}\"", command);
    thread::Builder::new().name(command.clone()).spawn(|| {
        Command::new(command)
            .stdout(Stdio::null())
            .spawn()
            .expect("Could not spawn command")
    }).expect("Unable to spawn thread");
    Ok(())
}

/// Kills a PID with the given signal
///
/// Returns false if it could not send the signal to that process
fn kill(_: &Lua, (pid, sig): (libc::pid_t, libc::c_int)) -> rlua::Result<bool> {
    Ok(nix::sys::signal::kill(pid, sig).is_ok())
}

fn set_preferred_icon_size(lua: &Lua, val: u32) -> rlua::Result<()> {
    let mut awesome_state: AwesomeState = lua.globals().get::<_, Table>("awesome")?.get("__data")?;
    awesome_state.preferred_icon_size = val;
    lua.globals().get::<_, Table>("awesome")?.set("__data", awesome_state.to_lua(lua)?)

}

fn quit(_: &Lua, _: ()) -> rlua::Result<()> {
    ::rustwlc::terminate();
    Ok(())
}

/// No need to sync in Wayland
fn sync(_: &Lua, _: ()) -> rlua::Result<()> { Ok(()) }

fn set_xproperty(_: &Lua, _: Value) -> rlua::Result<()> {
    warn!("set_xproperty not supported");
    Ok(())
}

fn get_xproperty(_: &Lua, _: Value) -> rlua::Result<()> {
    warn!("get_xproperty not supported");
    Ok(())
}

fn xkb_set_layout_group(_: &Lua, _group: i32) -> rlua::Result<()> {
    warn!("xkb_set_layout_group not supported; Wait until wlroots");
    Ok(())
}

fn xkb_get_layout_group(_: &Lua, _: ()) -> rlua::Result<i32> {
    warn!("xkb_get_layout_group not supported; Wait until wlroots");
    warn!("Returning dummy data so I can move forward");
    warn!("Replace me before release!");
    Ok(0)
}

fn xrdb_get_value(lua: &Lua, (_resource_class, resource_name): (String, String))
                  -> rlua::Result<Value> {
    if &resource_name == "Xft.dpi" {
        return Ok("1".to_lua(lua)?)
    }
    warn!("xrdb_get_value not supported");
    Ok(Value::Nil)
}
<|endoftext|>


<commit_before>use super::super::{Y, X, Coord, Grid};
use super::*;

extern crate rand;

use rand::{Rng, distributions};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Edge {
    Undecided,
    Line,
    Blank,
}

struct AnswerField {
    height: i32,
    width: i32,
    field: Grid<Edge>,
    invalid: bool,
}

impl AnswerField {
    fn new(height: i32, width: i32) -> AnswerField {
        AnswerField {
            height: height,
            width: width,
            field: Grid::new(2 * height - 1, 2 * width - 1, Edge::Undecided),
            invalid: false,
        }
    }
    fn get(&self, cd: Coord) -> Edge {
        if self.field.is_valid_coord(cd) {
            self.field[cd]
        } else {
            Edge::Blank
        }
    }
    /// Counts the number of (Line, Undecided) around `cd`
    fn count_neighbor(&self, cd: Coord) -> (i32, i32) {
        let (Y(y), X(x)) = cd;
        let mut line = 0;
        let mut undecided = 0;
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        for &(dy, dx) in &dirs {
            let e = self.get((Y(y + dy), X(x + dx)));
            if e == Edge::Line {
                line += 1;
            } else if e == Edge::Undecided {
                undecided += 1;
            }
        }
        (line, undecided)
    }
    /// Returns all neighbors whose state is `Undecided` around `cd`
    fn undecided_neighbors(&self, cd: Coord) -> Vec<Coord> {
        let (Y(y), X(x)) = cd;
        let mut ret = vec![];
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        for &(dy, dx) in &dirs {
            let cd2 = (Y(y + dy), X(x + dx));
            let e = self.get(cd2);
            if e == Edge::Undecided {
                ret.push(cd2);
            }
        }
        ret
    }
    fn decide(&mut self, cd: Coord, state: Edge) {
        let current = self.field[cd];
        if current != Edge::Undecided {
            if current != state {
                self.invalid = true;
            }
            return;
        }
        self.field[cd] = state;

        // check incident vertices
        let (Y(y), X(x)) = cd;
        if y % 2 == 1 {
            self.inspect((Y(y - 1), X(x)));
            self.inspect((Y(y + 1), X(x)));
        } else {
            self.inspect((Y(y), X(x - 1)));
            self.inspect((Y(y), X(x + 1)));
        }

        // check for canonization rule
        if state == Edge::Line {
            if y % 2 == 1 {
                let related = [
                    (Y(y), X(x - 2)),
                    (Y(y - 1), X(x - 1)),
                    (Y(y + 1), X(x - 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
                let related = [
                    (Y(y), X(x + 2)),
                    (Y(y - 1), X(x + 1)),
                    (Y(y + 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
            } else {
                let related = [
                    (Y(y - 2), X(x)),
                    (Y(y - 1), X(x - 1)),
                    (Y(y - 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
                let related = [
                    (Y(y + 2), X(x)),
                    (Y(y + 1), X(x - 1)),
                    (Y(y + 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
            }
        }
    }
    /// Inspect vertex (y, x)
    fn inspect(&mut self, (Y(y), X(x)): Coord) {
        let (line, undecided) = self.count_neighbor((Y(y), X(x)));
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        if line == 0 {
            if undecided == 0 {
                self.invalid = true;
                return;
            }
            if undecided == 1 {
                for &(dy, dx) in &dirs {
                    let e = self.get((Y(y + dy), X(x + dx)));
                    if e == Edge::Undecided {
                        self.decide((Y(y + dy), X(x + dx)), Edge::Line);
                    }
                }
            }
        } else if line == 2 {
            for &(dy, dx) in &dirs {
                let e = self.get((Y(y + dy), X(x + dx)));
                if e == Edge::Undecided {
                    self.decide((Y(y + dy), X(x + dx)), Edge::Blank);
                }
            }
        }
    }
}

fn generate_placement<R: Rng>(height: i32, width: i32, rng: &mut R) {
    let mut field = AnswerField::new(height, width);

    loop {
        let mut cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let y = y * 2;
                let x = x * 2;
                let (line, undecided) = field.count_neighbor((Y(y), X(x)));
                if (line == 0 && undecided == 2) || (line == 1 && undecided > 0) {
                    cand.push((Y(y), X(x)));
                }
            }
        }

        if cand.len() == 0 { break; }

        let idx = rng.gen_range(0, cand.len());
        let cd = cand[idx];

        if field.count_neighbor(cd) == (0, 2) {
            let nbs = field.undecided_neighbors(cd);
            if rng.next_f64() < 0.9f64 {
                // as angle
                field.decide(nbs[0], Edge::Line);
                field.decide(nbs[1], Edge::Line);
            } else {
                // as an endpoint
                let i = rng.gen_range(0, 2);
                field.decide(nbs[i], Edge::Line);
                field.decide(nbs[(1 - i)], Edge::Blank);
            }
        } else {
            let nbs = field.undecided_neighbors(cd);

            if rng.next_f64() < 1.0f64 {
                // extend
                let i = rng.gen_range(0, nbs.len());
                field.decide(nbs[i], Edge::Line);
            } else {
                // terminate
                for nb in nbs {
                    field.decide(nb, Edge::Blank);
                }
            }
        }
    }

    if field.invalid { return; }

    let mut ids = Grid::new(height, width, -1);
    let mut id = 1;
    for y in 0..height {
        for x in 0..width {
            if ids[(Y(y), X(x))] == -1 {
                fill_line_id((Y(y), X(x)), &field, &mut ids, id);
                id += 1;
            }
        }
    }

    let mut line_len = vec![0; id as usize];
    for y in 0..height {
        for x in 0..width {
            line_len[ids[(Y(y), X(x))] as usize] += 1;
        }
    }
    for i in 1..id {
        if line_len[i as usize] <= 3 { return; }
    }

    for y in 0..(2 * height - 1) {
        for x in 0..(2 * width - 1) {
            if y % 2 == 1 && x % 2 == 0 {
                if (ids[(Y(y / 2), X(x / 2))] == ids[(Y(y / 2 + 1), X(x / 2))]) != (field.get((Y(y), X(x))) == Edge::Line) { return; }
            } else if y % 2 == 0 && x % 2 == 1 {
                if (ids[(Y(y / 2), X(x / 2))] == ids[(Y(y / 2), X(x / 2 + 1))]) != (field.get((Y(y), X(x))) == Edge::Line) { return; }
            }
        }
    }
    for y in 0..(2 * height - 1) {
        for x in 0..(2 * width - 1) {
            match (y % 2, x % 2) {
                (0, 0) => print!("+"),
                (0, 1) => print!("{}", match field.get((Y(y), X(x))) {
                    Edge::Undecided => ' ',
                    Edge::Line => '-',
                    Edge::Blank => ' ',
                }),
                (1, 0) => print!("{}", match field.get((Y(y), X(x))) {
                    Edge::Undecided => ' ',
                    Edge::Line => '|',
                    Edge::Blank => ' ',
                }),
                (1, 1) => print!(" "),
                _ => unreachable!(),
            }
        }
        println!();
    }
    for y in 0..height {
        for x in 0..width {
            if field.count_neighbor((Y(y * 2), X(x * 2))) == (1, 0) {
                print!("{:2} ", ids[(Y(y), X(x))]);
            } else {
                print!(".. ");
            }
        }
        println!();
    }
    println!("----------------");
}
fn fill_line_id(cd: Coord, field: &AnswerField, ids: &mut Grid<i32>, id: i32) {
    if ids[cd] != -1 { return; }
    ids[cd] = id;
    let (Y(y), X(x)) = cd;

    let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
    for &(dy, dx) in &dirs {
        if field.get((Y(y * 2 + dy), X(x * 2 + dx))) == Edge::Line {
            fill_line_id((Y(y + dy), X(x + dx)), field, ids, id);
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_placement_generator() {
        let mut rng = ::rand::thread_rng();
        println!();
        for _ in 0..1000 {
            generate_placement(10, 18, &mut rng);
        }
        assert!(false);
    }
}
<commit_msg>Numberlink: return a problem candidate instead of printing it in generate_placement<commit_after>use super::super::{Y, X, Coord, Grid};
use super::*;

extern crate rand;

use rand::{Rng, distributions};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Edge {
    Undecided,
    Line,
    Blank,
}

struct AnswerField {
    height: i32,
    width: i32,
    field: Grid<Edge>,
    invalid: bool,
}

impl AnswerField {
    fn new(height: i32, width: i32) -> AnswerField {
        AnswerField {
            height: height,
            width: width,
            field: Grid::new(2 * height - 1, 2 * width - 1, Edge::Undecided),
            invalid: false,
        }
    }
    fn get(&self, cd: Coord) -> Edge {
        if self.field.is_valid_coord(cd) {
            self.field[cd]
        } else {
            Edge::Blank
        }
    }
    /// Counts the number of (Line, Undecided) around `cd`
    fn count_neighbor(&self, cd: Coord) -> (i32, i32) {
        let (Y(y), X(x)) = cd;
        let mut line = 0;
        let mut undecided = 0;
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        for &(dy, dx) in &dirs {
            let e = self.get((Y(y + dy), X(x + dx)));
            if e == Edge::Line {
                line += 1;
            } else if e == Edge::Undecided {
                undecided += 1;
            }
        }
        (line, undecided)
    }
    /// Returns all neighbors whose state is `Undecided` around `cd`
    fn undecided_neighbors(&self, cd: Coord) -> Vec<Coord> {
        let (Y(y), X(x)) = cd;
        let mut ret = vec![];
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        for &(dy, dx) in &dirs {
            let cd2 = (Y(y + dy), X(x + dx));
            let e = self.get(cd2);
            if e == Edge::Undecided {
                ret.push(cd2);
            }
        }
        ret
    }
    fn decide(&mut self, cd: Coord, state: Edge) {
        let current = self.field[cd];
        if current != Edge::Undecided {
            if current != state {
                self.invalid = true;
            }
            return;
        }
        self.field[cd] = state;

        // check incident vertices
        let (Y(y), X(x)) = cd;
        if y % 2 == 1 {
            self.inspect((Y(y - 1), X(x)));
            self.inspect((Y(y + 1), X(x)));
        } else {
            self.inspect((Y(y), X(x - 1)));
            self.inspect((Y(y), X(x + 1)));
        }

        // check for canonization rule
        if state == Edge::Line {
            if y % 2 == 1 {
                let related = [
                    (Y(y), X(x - 2)),
                    (Y(y - 1), X(x - 1)),
                    (Y(y + 1), X(x - 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
                let related = [
                    (Y(y), X(x + 2)),
                    (Y(y - 1), X(x + 1)),
                    (Y(y + 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
            } else {
                let related = [
                    (Y(y - 2), X(x)),
                    (Y(y - 1), X(x - 1)),
                    (Y(y - 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
                let related = [
                    (Y(y + 2), X(x)),
                    (Y(y + 1), X(x - 1)),
                    (Y(y + 1), X(x + 1)),
                ];
                for i in 0..3 {
                    if self.get(related[i]) == Edge::Line {
                        self.decide(related[(i + 1) % 3], Edge::Blank);
                        self.decide(related[(i + 2) % 3], Edge::Blank);
                    }
                }
            }
        }
    }
    /// Inspect vertex (y, x)
    fn inspect(&mut self, (Y(y), X(x)): Coord) {
        let (line, undecided) = self.count_neighbor((Y(y), X(x)));
        let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
        if line == 0 {
            if undecided == 0 {
                self.invalid = true;
                return;
            }
            if undecided == 1 {
                for &(dy, dx) in &dirs {
                    let e = self.get((Y(y + dy), X(x + dx)));
                    if e == Edge::Undecided {
                        self.decide((Y(y + dy), X(x + dx)), Edge::Line);
                    }
                }
            }
        } else if line == 2 {
            for &(dy, dx) in &dirs {
                let e = self.get((Y(y + dy), X(x + dx)));
                if e == Edge::Undecided {
                    self.decide((Y(y + dy), X(x + dx)), Edge::Blank);
                }
            }
        }
    }
}

pub fn generate_placement<R: Rng>(height: i32, width: i32, rng: &mut R) -> Option<Grid<Clue>> {
    let mut field = AnswerField::new(height, width);

    loop {
        let mut cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let y = y * 2;
                let x = x * 2;
                let (line, undecided) = field.count_neighbor((Y(y), X(x)));
                if (line == 0 && undecided == 2) || (line == 1 && undecided > 0) {
                    cand.push((Y(y), X(x)));
                }
            }
        }

        if cand.len() == 0 { break; }

        let idx = rng.gen_range(0, cand.len());
        let cd = cand[idx];

        if field.count_neighbor(cd) == (0, 2) {
            let nbs = field.undecided_neighbors(cd);
            if rng.next_f64() < 0.9f64 {
                // as angle
                field.decide(nbs[0], Edge::Line);
                field.decide(nbs[1], Edge::Line);
            } else {
                // as an endpoint
                let i = rng.gen_range(0, 2);
                field.decide(nbs[i], Edge::Line);
                field.decide(nbs[(1 - i)], Edge::Blank);
            }
        } else {
            let nbs = field.undecided_neighbors(cd);

            if rng.next_f64() < 1.0f64 {
                // extend
                let i = rng.gen_range(0, nbs.len());
                field.decide(nbs[i], Edge::Line);
            } else {
                // terminate
                for nb in nbs {
                    field.decide(nb, Edge::Blank);
                }
            }
        }
    }

    if field.invalid { return None; }

    let mut ids = Grid::new(height, width, -1);
    let mut id = 1;
    for y in 0..height {
        for x in 0..width {
            if ids[(Y(y), X(x))] == -1 {
                fill_line_id((Y(y), X(x)), &field, &mut ids, id);
                id += 1;
            }
        }
    }

    let mut line_len = vec![0; id as usize];
    for y in 0..height {
        for x in 0..width {
            line_len[ids[(Y(y), X(x))] as usize] += 1;
        }
    }
    for i in 1..id {
        if line_len[i as usize] <= 3 { return None; }
    }

    let mut end_count = vec![0; id as usize];
    for y in 0..height {
        for x in 0..width {
            if field.count_neighbor((Y(y * 2), X(x * 2))) == (1, 0) {
                end_count[ids[(Y(y), X(x))] as usize] += 1;
            }
        }
    }
    for i in 1..id {
        if end_count[i as usize] != 2 { return None; }
    }

    for y in 0..(2 * height - 1) {
        for x in 0..(2 * width - 1) {
            if y % 2 == 1 && x % 2 == 0 {
                if (ids[(Y(y / 2), X(x / 2))] == ids[(Y(y / 2 + 1), X(x / 2))]) != (field.get((Y(y), X(x))) == Edge::Line) { return None; }
            } else if y % 2 == 0 && x % 2 == 1 {
                if (ids[(Y(y / 2), X(x / 2))] == ids[(Y(y / 2), X(x / 2 + 1))]) != (field.get((Y(y), X(x))) == Edge::Line) { return None; }
            }
        }
    }

    let mut ret = Grid::new(height, width, NO_CLUE);
    for y in 0..height {
        for x in 0..width {
            if field.count_neighbor((Y(y * 2), X(x * 2))) == (1, 0) {
                ret[(Y(y), X(x))] = Clue(ids[(Y(y), X(x))]);
            }
        }
    }

    Some(ret)
}
fn fill_line_id(cd: Coord, field: &AnswerField, ids: &mut Grid<i32>, id: i32) {
    if ids[cd] != -1 { return; }
    ids[cd] = id;
    let (Y(y), X(x)) = cd;

    let dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)];
    for &(dy, dx) in &dirs {
        if field.get((Y(y * 2 + dy), X(x * 2 + dx))) == Edge::Line {
            fill_line_id((Y(y + dy), X(x + dx)), field, ids, id);
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    context,
    cpu_id,
    interrupt::stack_trace,
    syscall,
    syscall::flag::*,

    with_exception_stack,
    exception_stack,
};

exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| {
    println!("Synchronous exception at EL1 with SP0");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
    println!("Synchronous exception at EL1 with SPx");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el0, |stack| {
    with_exception_stack!(|stack| {
        let fp;
        asm!("mov {}, fp", out(reg) fp);

        let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26;
        if exception_code != 0b010101 {
            println!("FATAL: Not an SVC induced synchronous exception");
            stack.dump();
            stack_trace();
            println!("CPU {}, PID {:?}", cpu_id(), context::context_id());
            loop {}
        }

        let scratch = &stack.scratch;
        syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack)
    });
});

exception_stack!(unhandled_exception, |stack| {
    println!("Unhandled exception");
    stack.dump();
    stack_trace();
    loop {}
});
<commit_msg>Print context name in exception<commit_after>use crate::{
    context,
    cpu_id,
    interrupt::stack_trace,
    syscall,
    syscall::flag::*,

    with_exception_stack,
    exception_stack,
};

exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| {
    println!("Synchronous exception at EL1 with SP0");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
    println!("Synchronous exception at EL1 with SPx");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el0, |stack| {
    with_exception_stack!(|stack| {
        let fp;
        asm!("mov {}, fp", out(reg) fp);

        let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26;
        if exception_code != 0b010101 {
            println!("FATAL: Not an SVC induced synchronous exception");
            stack.dump();
            stack_trace();

            println!("CPU {}, PID {:?}", cpu_id(), context::context_id());

            // This could deadlock, but at this point we are going to halt anyways
            {
                let contexts = context::contexts();
                if let Some(context_lock) = contexts.current() {
                    let context = context_lock.read();
                    println!("NAME: {}", *context.name.read());
                }
            }

            // Halt
            loop {}
        }

        let scratch = &stack.scratch;
        syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack)
    });
});

exception_stack!(unhandled_exception, |stack| {
    println!("Unhandled exception");
    stack.dump();
    stack_trace();
    loop {}
});
<|endoftext|>