<commit_before>extern crate regex;
extern crate getopts;
use std::collections::{HashMap, HashSet};
use std::{env, fs, io};
use std::io::prelude::*;
mod options;
use options::*;
use std::process;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
macro_rules! println_stderr(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
        )
    );

const KEY_FILE: &'static str = "KEY_FILE";
const ENV: &'static str = "ENV";
const MISSING: &'static str = "Missing properties";

fn replace_var(line: String,
               keys: &Option<HashMap<String, ValueAndSource>>,
               props_first: bool,
               used_keys: &mut HashMap<&'static str, Vec<(String, String)>>,
               result: &mut Vec<String>) {
    let re = regex!(r"(?P<full>\$\{\s*(?P<var>[^\}]*)\s*\})");
    let mut str_line: String = line.clone();

    for cap in re.captures_iter(&*str_line.clone()) {
        cap.name("var").map(|v| {
            let env_prop = env_or_prop(v.trim(), props_first, keys.clone()).map(|v2| {
                str_line = re.replace(&*str_line, &*v2.1);
                (v2.0, v2.1, v2.2)
            });

            env_prop.and_then(|v2| {
                used_keys.get_mut(&v2.2)
                         .and_then(|r| Some(r.push((v2.0.clone(), v2.1.clone()))))
                         .or_else(|| {
                             used_keys.insert(v2.2.clone(), vec![(v2.0.clone(), v2.1.clone())]);
                             Some(())
                         })
            })
        });
    }
    result.push(str_line.to_string());
}

fn env_or_prop(key: &str,
               props_first: bool,
               keys: &Option<HashMap<String, ValueAndSource>>)
               -> Option<(String, String, &'static str)> {
    match *keys {
        Some(ref k) => {
            let prop = k.get(key).and_then(|v| Some(v.clone()));
            let env = env::var_os(key).map(|v2| v2.clone().into_string().ok().unwrap());
            match (prop, props_first) {
                (Some(prop), true) => {
                    Some((key.to_string(), prop.value.clone(), KEY_FILE))
                }
                (Some(prop), false) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), prop.value.clone(), KEY_FILE)),
                    }
                }
                (None, true) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), key.to_string(), MISSING)),
                    }

                }
                (None, false) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), key.to_string(), MISSING)),
                    }

                }
            }
        }
        None => {
            match env::var_os(key)
                      .map(|v| v.into_string().ok())
                      .unwrap_or(None) {
                Some(e) => {
                    Some((key.to_string(), e.to_string(), ENV))
                }
                None => {
                    Some((key.to_string(), key.to_string(), MISSING))
                }
            }
        }
    }
}

fn process(file: fs::File,
           used_keys: &mut HashMap<&'static str, Vec<(String, String)>>,
           dict: Option<HashMap<String, ValueAndSource>>,
           props_first: bool)
           -> Vec<String> {
    let buf_reader = io::BufReader::new(&file);
    let mut result: Vec<String> = vec![];

    for line in buf_reader.lines() {
        replace_var(line.unwrap(), &dict, props_first, used_keys, &mut result);
    }

    result
}

fn extract_keys(file: fs::File /* key_map: Option<HashMap<String, ValueAndSource>> */)
                -> HashMap<String, String> {
    let key_regex = regex!(r"^\s*(?P<key>\S*)\s*=\s*(?P<val>.*)");
    let buf_reader = io::BufReader::new(&file);
    let mut keys = HashMap::new();/*,
                                    };*/

    for line in buf_reader.lines().enumerate() {
        for cap in key_regex.captures_iter(&*line.1
                                                 .ok()
                                                 .expect("Could not read line")) {
            let key = cap.name("key")
                         .unwrap_or("???");
            let val = cap.name("val")
                         .unwrap_or("???");
            if !keys.contains_key(key) {
                keys.insert(key.to_string(),
                            // ValueAndSource {
                            // value:
                            val.to_string() /* ,
                                             * source: "".to_string(),
                                             * } */);
            }
        }
    }

    keys
}

#[derive(Debug)]
struct ValueAndSource {
    value: String,
    source: String,
}

fn insert_if_not_exist(dict: &mut HashMap<String, ValueAndSource>,
                       matches: HashMap<String, String>,
                       filename: String) {
    for key_val in matches.iter() {
        let key: String = (*key_val.0).clone();
        let val: String = (*key_val.1).clone();
        if !dict.contains_key(&key) {
            dict.insert(key,
                        ValueAndSource {
                            value: val,
                            source: filename.clone(),
                        });
        }
    }
}

fn read_keyfiles_and_generate_dict(key_filenames: Vec<String>)
                                   -> Option<HashMap<String, ValueAndSource>> {
    let mut dict: HashMap<String, ValueAndSource> = HashMap::new();
    for filename in key_filenames {
        fs::File::open(&filename)
            .and_then(|f| Ok(extract_keys(f)))
            .map(|v| {
                insert_if_not_exist(&mut dict, v, filename);
            });
    }

    match dict.len() {
        0 => None,
        _ => Some(dict),
    }
}

fn create_file(arg_parser: &ApplicationOptions, filename: &String) -> fs::File {
    match fs::File::create(filename) {
        Ok(f) => Some(f),
        Err(e) => {
            println_stderr!("ERROR: Could not create file: {}\n{}\n", filename, e);
            arg_parser.print_usage_and_panic();
            None
        }
    }
    .unwrap()
}

fn open_file(arg_parser: &ApplicationOptions, filename: &String) -> fs::File {
    match fs::File::open(filename) {
        Ok(f) => Some(f),
        Err(e) => {
            println_stderr!("ERROR: Could not open file: {}\n{}\n", filename, e);
            arg_parser.print_usage_and_panic();
            None
        }
    }
    .unwrap()
}

struct Settings<'a> {
    key_filenames: Vec<String>,
    prop_filename: &'a String,
    result_filename: &'a String,
    props_first: bool,
}

fn calc_result(arg_parser: &ApplicationOptions, settings: Settings) {
    let prop_file = open_file(&arg_parser, &settings.prop_filename);
    let mut result_buff = Vec::new();
    let mut used_keys = HashMap::new();

    let keys = read_keyfiles_and_generate_dict(settings.key_filenames);

    for line in process(prop_file, &mut used_keys, keys, settings.props_first).iter() {
        result_buff.push(line.clone());
    }

    println!("======== RESULTS ========");

    let env_vars = used_keys.get(ENV);
    if env_vars.is_some() {
        let vars = env_vars.unwrap();
        println!("Environment variables:");
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
    }

    let prop_vars = used_keys.get(KEY_FILE);
    if prop_vars.is_some() {
        let vars = prop_vars.unwrap();
        // println!("From keyfile {}:", key_filename.unwrap()) ;
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
    }

    let missing_vars = used_keys.get(MISSING);
    if missing_vars.is_some() {
        let vars = missing_vars.unwrap();
        println!("Missing variables found in {}:", settings.prop_filename);
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
        println_stderr!("ERROR: Must replace all found variables\n\n");
        process::exit(1);
    }

    if env_vars.is_none() && prop_vars.is_none() && missing_vars.is_none() {
        println!("[No variables to substitute!]\n");
    }

    let mut result_file = create_file(&arg_parser, settings.result_filename);

    for line in result_buff {
        result_file.write_all(&format!("{}\n", line).as_bytes()).unwrap();
    }
    result_file.flush().unwrap();

    println!("...DONE!");
}

fn create_arg_parser() -> ApplicationOptions {
    ApplicationOptions::new(|| {
        let mut o = OptionsAndFlags::new();
        o.parsing_style(getopts::ParsingStyle::StopAtFirstFree);
        o.opt("k",
              "keys",
              "keyfile with variable substitutions",
              "FILE",
              getopts::HasArg::Yes,
              getopts::Occur::Multi)
         .unwrap();
        o.opt("p",
              "props-first",
              "properties takes precedence over environment variables (default: off)",
              "",
              getopts::HasArg::No,
              getopts::Occur::Optional)
         .unwrap();
        o.opt("?",
              "help",
              "print this help menu",
              "",
              getopts::HasArg::No,
              getopts::Occur::Optional)
         .unwrap();
        Ok(o)
    })
}

struct PropAndResultFilenames<'a> {
    prop_filename: &'a String,
    result_filename: &'a String,
}

fn get_prop_and_result_filename<'a>(arg_parser: &'a ApplicationOptions,
                                    free_args: &'a Vec<String>)
                                    -> PropAndResultFilenames<'a> {
    match free_args.len() {
        1 => {
            // Replace vars in the provided file
            PropAndResultFilenames {
                prop_filename: &free_args[0],
                result_filename: &free_args[0],
            }
        }
        2 => {
            // Replace vars into a separate output file
            PropAndResultFilenames {
                prop_filename: &free_args[0],
                result_filename: &free_args[1],
            }
        }
        _ => {
            println_stderr!("Wrong number of file parameters: {}", free_args.len());
            arg_parser.print_usage();
            process::exit(1);
        }
    }
}

fn get_props_first(matches: &Box<getopts::Matches>) -> bool {
    if matches.opt_present("p") {
        true
    } else {
        false
    }

}

fn get_parsed_args(arg_parser: &ApplicationOptions) -> Box<getopts::Matches> {
Box::new(arg_parser.parse().unwrap_or_else(|e| {
        println_stderr!("{}", e);
        process::exit(1);
    }))
}

#[allow(dead_code)]
fn main() {
    let arg_parser: ApplicationOptions = create_arg_parser();
    let matches = get_parsed_args(&arg_parser);

    let prop_and_result_filenames = get_prop_and_result_filename(&arg_parser,
                                                                 &matches.free);
    calc_result(&arg_parser,
                Settings {
                    key_filenames: matches.opt_strs("k"),
                    prop_filename: prop_and_result_filenames.prop_filename,
                    result_filename: prop_and_result_filenames.result_filename,
                    props_first: get_props_first(&matches),
                });
}

#[cfg(test)]
mod tests {
    use super::replace_var;
    use std::collections::HashMap;
    use super::ValueAndSource;

    struct TestData {
        key_map: HashMap<String, ValueAndSource>,
        used_keys: HashMap<&'static str, Vec<(String, String)>>,
        result: Vec<String>,
    }

    fn create_test_data(keys: Vec<(&str, &str)>) -> TestData {
        let mut test_data = TestData {
            key_map: HashMap::new(),
            used_keys: HashMap::new(),
            result: Vec::new(),
        };

        for k in keys {
            test_data.key_map.insert(k.0.to_string(),
                                     ValueAndSource {
                                         value: k.1.to_string(),
                                         source: "".to_string(),
                                     });
        }

        test_data
    }

    #[test]
    fn can_sub_single_var() {
        let mut test_data = create_test_data(vec![("val", "world!")]);
        replace_var("Hello ${val}".to_string(),
                    &Some(test_data.key_map),
                    true,
                    &mut test_data.used_keys,
                    &mut test_data.result);
        assert!(test_data.result.len() == 1);
        assert!(test_data.used_keys[super::KEY_FILE][0].0 == "val".to_string());
        assert!(test_data.result[0] == "Hello world!".to_string());
    }
}
<commit_msg>Remove some commented code<commit_after>extern crate regex;
extern crate getopts;
use std::collections::{HashMap};
use std::{env, fs, io};
use std::io::prelude::*;
mod options;
use options::*;
use std::process;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
macro_rules! println_stderr(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
        )
    );

const KEY_FILE: &'static str = "KEY_FILE";
const ENV: &'static str = "ENV";
const MISSING: &'static str = "Missing properties";

fn replace_var(line: String,
               keys: &Option<HashMap<String, ValueAndSource>>,
               props_first: bool,
               used_keys: &mut HashMap<&'static str, Vec<(String, String)>>,
               result: &mut Vec<String>) {
    let re = regex!(r"(?P<full>\$\{\s*(?P<var>[^\}]*)\s*\})");
    let mut str_line: String = line.clone();

    for cap in re.captures_iter(&*str_line.clone()) {
        cap.name("var").map(|v| {
            let env_prop = env_or_prop(v.trim(), props_first, keys.clone()).map(|v2| {
                str_line = re.replace(&*str_line, &*v2.1);
                (v2.0, v2.1, v2.2)
            });

            env_prop.and_then(|v2| {
                used_keys.get_mut(&v2.2)
                         .and_then(|r| Some(r.push((v2.0.clone(), v2.1.clone()))))
                         .or_else(|| {
                             used_keys.insert(v2.2.clone(), vec![(v2.0.clone(), v2.1.clone())]);
                             Some(())
                         })
            })
        });
    }
    result.push(str_line.to_string());
}

fn env_or_prop(key: &str,
               props_first: bool,
               keys: &Option<HashMap<String, ValueAndSource>>)
               -> Option<(String, String, &'static str)> {
    match *keys {
        Some(ref k) => {
            let prop = k.get(key).and_then(|v| Some(v.clone()));
            let env = env::var_os(key).map(|v2| v2.clone().into_string().ok().unwrap());
            match (prop, props_first) {
                (Some(prop), true) => {
                    Some((key.to_string(), prop.value.clone(), KEY_FILE))
                }
                (Some(prop), false) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), prop.value.clone(), KEY_FILE)),
                    }
                }
                (None, true) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), key.to_string(), MISSING)),
                    }

                }
                (None, false) => {
                    match env {
                        Some(e) => {
                            Some((key.to_string(), e.to_string(), ENV))
                        }
                        None => Some((key.to_string(), key.to_string(), MISSING)),
                    }

                }
            }
        }
        None => {
            match env::var_os(key)
                      .map(|v| v.into_string().ok())
                      .unwrap_or(None) {
                Some(e) => {
                    Some((key.to_string(), e.to_string(), ENV))
                }
                None => {
                    Some((key.to_string(), key.to_string(), MISSING))
                }
            }
        }
    }
}

fn process(file: fs::File,
           used_keys: &mut HashMap<&'static str, Vec<(String, String)>>,
           dict: Option<HashMap<String, ValueAndSource>>,
           props_first: bool)
           -> Vec<String> {
    let buf_reader = io::BufReader::new(&file);
    let mut result: Vec<String> = vec![];

    for line in buf_reader.lines() {
        replace_var(line.unwrap(), &dict, props_first, used_keys, &mut result);
    }

    result
}

fn extract_keys(file: fs::File) -> HashMap<String, String> {
    let key_regex = regex!(r"^\s*(?P<key>\S*)\s*=\s*(?P<val>.*)");
    let buf_reader = io::BufReader::new(&file);
    let mut keys = HashMap::new();

    for line in buf_reader.lines().enumerate() {
        for cap in key_regex.captures_iter(&*line.1
                                                 .ok()
                                                 .expect("Could not read line")) {
            let key = cap.name("key")
                         .unwrap_or("???");
            let val = cap.name("val")
                         .unwrap_or("???");
            if !keys.contains_key(key) {
                keys.insert(key.to_string(), val.to_string());
            }
        }
    }

    keys
}

#[derive(Debug)]
struct ValueAndSource {
    value: String,
    source: String,
}

fn insert_if_not_exist(dict: &mut HashMap<String, ValueAndSource>,
                       matches: HashMap<String, String>,
                       filename: String) {
    for key_val in matches.iter() {
        let key: String = (*key_val.0).clone();
        let val: String = (*key_val.1).clone();
        if !dict.contains_key(&key) {
            dict.insert(key,
                        ValueAndSource {
                            value: val,
                            source: filename.clone(),
                        });
        }
    }
}

fn read_keyfiles_and_generate_dict(key_filenames: Vec<String>)
                                   -> Option<HashMap<String, ValueAndSource>> {
    let mut dict: HashMap<String, ValueAndSource> = HashMap::new();
    for filename in key_filenames {
        fs::File::open(&filename)
            .and_then(|f| Ok(extract_keys(f)))
            .map(|v| {
                insert_if_not_exist(&mut dict, v, filename);
            });
    }

    match dict.len() {
        0 => None,
        _ => Some(dict),
    }
}

fn create_file(arg_parser: &ApplicationOptions, filename: &String) -> fs::File {
    match fs::File::create(filename) {
        Ok(f) => Some(f),
        Err(e) => {
            println_stderr!("ERROR: Could not create file: {}\n{}\n", filename, e);
            arg_parser.print_usage_and_panic();
            None
        }
    }
    .unwrap()
}

fn open_file(arg_parser: &ApplicationOptions, filename: &String) -> fs::File {
    match fs::File::open(filename) {
        Ok(f) => Some(f),
        Err(e) => {
            println_stderr!("ERROR: Could not open file: {}\n{}\n", filename, e);
            arg_parser.print_usage_and_panic();
            None
        }
    }
    .unwrap()
}

struct Settings<'a> {
    key_filenames: Vec<String>,
    prop_filename: &'a String,
    result_filename: &'a String,
    props_first: bool,
}

fn calc_result(arg_parser: &ApplicationOptions, settings: Settings) {
    let prop_file = open_file(&arg_parser, &settings.prop_filename);
    let mut result_buff = Vec::new();
    let mut used_keys = HashMap::new();

    let keys = read_keyfiles_and_generate_dict(settings.key_filenames);

    for line in process(prop_file, &mut used_keys, keys, settings.props_first).iter() {
        result_buff.push(line.clone());
    }

    println!("======== RESULTS ========");

    let env_vars = used_keys.get(ENV);
    if env_vars.is_some() {
        let vars = env_vars.unwrap();
        println!("Environment variables:");
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
    }

    let prop_vars = used_keys.get(KEY_FILE);
    if prop_vars.is_some() {
        let vars = prop_vars.unwrap();
        // println!("From keyfile {}:", key_filename.unwrap()) ;
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
    }

    let missing_vars = used_keys.get(MISSING);
    if missing_vars.is_some() {
        let vars = missing_vars.unwrap();
        println!("Missing variables found in {}:", settings.prop_filename);
        for v in vars {
            println!("${{{}}}", v.0);
        }
        println!("");
        println_stderr!("ERROR: Must replace all found variables\n\n");
        process::exit(1);
    }

    if env_vars.is_none() && prop_vars.is_none() && missing_vars.is_none() {
        println!("[No variables to substitute!]\n");
    }

    let mut result_file = create_file(&arg_parser, settings.result_filename);

    for line in result_buff {
        result_file.write_all(&format!("{}\n", line).as_bytes()).unwrap();
    }
    result_file.flush().unwrap();

    println!("...DONE!");
}

fn create_arg_parser() -> ApplicationOptions {
    ApplicationOptions::new(|| {
        let mut o = OptionsAndFlags::new();
        o.parsing_style(getopts::ParsingStyle::StopAtFirstFree);
        o.opt("k",
              "keys",
              "keyfile with variable substitutions",
              "FILE",
              getopts::HasArg::Yes,
              getopts::Occur::Multi)
         .unwrap();
        o.opt("p",
              "props-first",
              "properties takes precedence over environment variables (default: off)",
              "",
              getopts::HasArg::No,
              getopts::Occur::Optional)
         .unwrap();
        o.opt("?",
              "help",
              "print this help menu",
              "",
              getopts::HasArg::No,
              getopts::Occur::Optional)
         .unwrap();
        Ok(o)
    })
}

struct PropAndResultFilenames<'a> {
    prop_filename: &'a String,
    result_filename: &'a String,
}

fn get_prop_and_result_filename<'a>(arg_parser: &'a ApplicationOptions,
                                    free_args: &'a Vec<String>)
                                    -> PropAndResultFilenames<'a> {
    match free_args.len() {
        1 => {
            // Replace vars in the provided file
            PropAndResultFilenames {
                prop_filename: &free_args[0],
                result_filename: &free_args[0],
            }
        }
        2 => {
            // Replace vars into a separate output file
            PropAndResultFilenames {
                prop_filename: &free_args[0],
                result_filename: &free_args[1],
            }
        }
        _ => {
            println_stderr!("Wrong number of file parameters: {}", free_args.len());
            arg_parser.print_usage();
            process::exit(1);
        }
    }
}

fn get_props_first(matches: &Box<getopts::Matches>) -> bool {
    if matches.opt_present("p") {
        true
    } else {
        false
    }

}

fn get_parsed_args(arg_parser: &ApplicationOptions) -> Box<getopts::Matches> {
    Box::new(arg_parser.parse().unwrap_or_else(|e| {
        println_stderr!("{}", e);
        process::exit(1);
    }))
}

#[allow(dead_code)]
fn main() {
    let arg_parser: ApplicationOptions = create_arg_parser();
    let matches = get_parsed_args(&arg_parser);

    let prop_and_result_filenames = get_prop_and_result_filename(&arg_parser, &matches.free);
    calc_result(&arg_parser,
                Settings {
                    key_filenames: matches.opt_strs("k"),
                    prop_filename: prop_and_result_filenames.prop_filename,
                    result_filename: prop_and_result_filenames.result_filename,
                    props_first: get_props_first(&matches),
                });
}

#[cfg(test)]
mod tests {
    use super::replace_var;
    use std::collections::HashMap;
    use super::ValueAndSource;

    struct TestData {
        key_map: HashMap<String, ValueAndSource>,
        used_keys: HashMap<&'static str, Vec<(String, String)>>,
        result: Vec<String>,
    }

    fn create_test_data(keys: Vec<(&str, &str)>) -> TestData {
        let mut test_data = TestData {
            key_map: HashMap::new(),
            used_keys: HashMap::new(),
            result: Vec::new(),
        };

        for k in keys {
            test_data.key_map.insert(k.0.to_string(),
                                     ValueAndSource {
                                         value: k.1.to_string(),
                                         source: "".to_string(),
                                     });
        }

        test_data
    }

    #[test]
    fn can_sub_single_var() {
        let mut test_data = create_test_data(vec![("val", "world!")]);
        replace_var("Hello ${val}".to_string(),
                    &Some(test_data.key_map),
                    true,
                    &mut test_data.used_keys,
                    &mut test_data.result);
        assert!(test_data.result.len() == 1);
        assert!(test_data.used_keys[super::KEY_FILE][0].0 == "val".to_string());
        assert!(test_data.result[0] == "Hello world!".to_string());
    }
}
<|endoftext|>


<commit_before>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

const STDP_FIRE_RESET: Num = 0.1;
const STDP_DECAY: Num = 0.95;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num,

    _last_spike: TimeStep,
    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.

    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
            _last_spike: 0, // XXX
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    fn update_state(&mut self, time_step: TimeStep, future_spikes: &mut Vec<Vec<SynapseId>>) {
        //for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
        for i in 0 .. self.neurons.len() {
            let syn_i = self.neurons[i].i_ext + self.neurons[i].i_inp;

            let (new_state, fired) = self.neurons[i].state.step_1ms(syn_i, &self.neurons[i].config);
            self.neurons[i].state = new_state;

            // decay STDP
            self.neurons[i].stdp *= STDP_DECAY;

            if fired {
                // Reset the neurons STDP to a high value.
                self.neurons[i].stdp = STDP_FIRE_RESET;

                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in self.neurons[i].post_synapses.iter() {
                    let future = time_step + self.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in self.neurons[i].pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id as usize].pre_neuron as usize].stdp;
                    self.synapses[syn_id as usize].eff_d += stdp;
                }
            }
        }
    }

    fn update_synapse_weights(&mut self, min_syn_weight: Num, max_syn_weight: Num, eff_d_decay: Num) {
        for syn in self.synapses.iter_mut() {
            let new_weight = syn.weight + syn.eff_d;

            // Restrict synapse weight min_syn_weight .. max_syn_weight
            if new_weight < min_syn_weight {
                syn.weight = min_syn_weight;
            }
            else if new_weight > max_syn_weight {
                syn.weight = max_syn_weight;
            }
            else {
                syn.weight = new_weight;
            }
            syn.eff_d *= eff_d_decay; // decay
        }
    }

}

fn main() {
    const PARAMS : &'static [(&'static str, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    let external_inputs: &[(NeuronId, TimeStep, Num)] = &[
        (n1, 200, 7.0),
        (n1, 701, 0.0)
    ];

    // We use a cyclic buffer
    // We use (time_step % MAX_DELAY) as index into the futures_spike array
    let mut future_spikes: Vec<Vec<SynapseId>> = (0..MAX_DELAY as usize).map(|_| Vec::new()).collect();

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();

    let mut time_step: TimeStep = 0;

    while time_step <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }
        time_step += 1;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut future_spikes[(time_step % (MAX_DELAY as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, pre_neuron, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.pre_neuron, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_inp += weight;

                // whenever a spike arrives here at it's post_neuron, this means, that
                // the pre-neuron fired some time ago (delay time-steps). It can be the
                // case that the post_neuron has fired ealier, in which case we have to
                // depress the synapse according to the STDP rule.
                network.synapses[syn_fired as usize].eff_d += network.neurons[pre_neuron as usize].stdp - network.neurons[post_neuron as usize].stdp;
            }
            current_spikes.clear();
        }

        // set external inputs
        for &(n_id, at, current) in external_inputs {
            if time_step == at {
                network.neurons[n_id as usize].i_ext = current;
            }
        }

        network.update_state(time_step, &mut future_spikes);

        if time_step % 500 == 0 {
            // Update synapse weights every 10 ms
            network.update_synapse_weights(0.0, 10.0, 0.9);
        }
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.1)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<commit_msg>Factor out code into Simulator struct<commit_after>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

const STDP_FIRE_RESET: Num = 0.1;
const STDP_DECAY: Num = 0.95;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num,

    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.

    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    fn update_state(&mut self, time_step: TimeStep, future_spikes: &mut Vec<Vec<SynapseId>>) {
        //for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
        for i in 0 .. self.neurons.len() {
            let syn_i = self.neurons[i].i_ext + self.neurons[i].i_inp;

            let (new_state, fired) = self.neurons[i].state.step_1ms(syn_i, &self.neurons[i].config);
            self.neurons[i].state = new_state;

            // decay STDP
            self.neurons[i].stdp *= STDP_DECAY;

            if fired {
                // Reset the neurons STDP to a high value.
                self.neurons[i].stdp = STDP_FIRE_RESET;

                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in self.neurons[i].post_synapses.iter() {
                    let future = time_step + self.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in self.neurons[i].pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id as usize].pre_neuron as usize].stdp;
                    self.synapses[syn_id as usize].eff_d += stdp;
                }
            }
        }
    }

    fn update_synapse_weights(&mut self, min_syn_weight: Num, max_syn_weight: Num, eff_d_decay: Num) {
        for syn in self.synapses.iter_mut() {
            let new_weight = syn.weight + syn.eff_d;

            // Restrict synapse weight min_syn_weight .. max_syn_weight
            if new_weight < min_syn_weight {
                syn.weight = min_syn_weight;
            }
            else if new_weight > max_syn_weight {
                syn.weight = max_syn_weight;
            }
            else {
                syn.weight = new_weight;
            }
            syn.eff_d *= eff_d_decay; // decay
        }
    }
}

struct Simulator {
    current_time_step: TimeStep,
    max_delay: usize,

    // We use a cyclic buffer
    // We use (time_step % max_delay) as index into the futures_spike array
    future_spikes: Vec<Vec<SynapseId>>,
}

impl Simulator {
    fn new(max_delay: usize) -> Simulator {
        Simulator {
            current_time_step: 0,
            max_delay: max_delay,
            future_spikes: (0..(max_delay+1)).map(|_| Vec::new()).collect(),
        }
    }

    fn current_time_step(&self) -> TimeStep {
        self.current_time_step
    }

    fn step(&mut self, network: &mut Network, external_inputs: &[(NeuronId, TimeStep, Num)]) {
        let time_step = self.current_time_step;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut self.future_spikes[(time_step % (self.max_delay as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, pre_neuron, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.pre_neuron, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_inp += weight;

                // whenever a spike arrives here at it's post_neuron, this means, that
                // the pre-neuron fired some time ago (delay time-steps). It can be the
                // case that the post_neuron has fired ealier, in which case we have to
                // depress the synapse according to the STDP rule.
                network.synapses[syn_fired as usize].eff_d += network.neurons[pre_neuron as usize].stdp - network.neurons[post_neuron as usize].stdp;
            }
            current_spikes.clear();
        }

        // set external inputs
        for &(n_id, at, current) in external_inputs {
            if time_step == at {
                network.neurons[n_id as usize].i_ext = current;
            }
        }

        network.update_state(time_step, &mut self.future_spikes);

        self.current_time_step += 1;
    }
}

fn main() {
    const PARAMS : &'static [(&'static str, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    let external_inputs: &[(NeuronId, TimeStep, Num)] = &[
        (n1, 200, 7.0),
        (n1, 701, 0.0)
    ];

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();
    let mut sim = Simulator::new(MAX_DELAY as usize);

    while sim.current_time_step() <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }

        sim.step(&mut network, &external_inputs);

        if sim.current_time_step() % 500 == 0 {
            // Update synapse weights every 10 ms
            network.update_synapse_weights(0.0, 10.0, 0.9);
        }
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.1)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<|endoftext|>


<commit_before>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;
use ww::command::{PrimaryCommand, CommandProcessor};

use RoomId::*;

const MAX_ROOMS: usize = 20;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway = 1,
  AudienceChamber = 2,
}

// Ideally we'd actually just get rid of MapRoomId and add a constraint
// to Map<T> requiring that T be type-castable as usize, but I don't
// know how to do that, so...
impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

enum GameMode {
  Primary,
  Finished,
}

fn build_world(map: &mut Map<RoomId>) {
  map.room(Hallway).describe(
    "Hallway",
    "You are in the hallway. \
     There is a door to the south. \
     Through the windows to the north you can see a secret herb garden."
  );

  map.room(AudienceChamber).describe(
    "Audience Chamber",
    "This is the audience chamber. \
     There is a window to the west. By looking to the right \
     through it you can see the entrance to the castle. \
     Doors leave this room to the north, east, and south."
  );

  map.connect(Hallway, South, AudienceChamber);
}

fn run_game(map: &mut Map<RoomId>) {
  println!("Werewolves and Wanderer\n");

  let mut curr_mode = GameMode::Primary;
  let mut curr_room = Hallway;
  let mut show_desc = true;

  loop {
    match curr_mode {
      GameMode::Primary => {
        if show_desc {
          println!("{}", map.room(curr_room).description);
          show_desc = false;
        }

        match PrimaryCommand::get() {
          PrimaryCommand::Go(dir) => {
            if let Some(room) = map.room(curr_room).get_exit(dir) {
              curr_room = room;
              show_desc = true;
            } else {
              println!("You can't go that way.");
            }
          },
          PrimaryCommand::Look => { show_desc = true; }
          PrimaryCommand::Quit => { curr_mode = GameMode::Finished; }
        }
      },
      GameMode::Finished => { break; }
    }
  }

  println!("Farewell.");
}

fn main() {
  let mut rooms = [Room::new(); MAX_ROOMS];
  let mut map = Map::new(&mut rooms);

  build_world(&mut map);
  run_game(&mut map);
}
<commit_msg>Factor out GameState struct.<commit_after>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;
use ww::command::{PrimaryCommand, CommandProcessor};

use RoomId::*;

const MAX_ROOMS: usize = 20;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway = 1,
  AudienceChamber = 2,
}

// Ideally we'd actually just get rid of MapRoomId and add a constraint
// to Map<T> requiring that T be type-castable as usize, but I don't
// know how to do that, so...
impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

#[derive(Debug, PartialEq, Copy, Clone)]
enum GameMode {
  Primary,
  Finished,
}

struct GameState<'a> {
  map: &'a mut Map<'a, RoomId>,
  pub curr_mode: GameMode,
  curr_room: RoomId,
  show_desc: bool,
}

impl<'a> GameState<'a> {
  pub fn new(map: &'a mut Map<'a, RoomId>) -> Self {
    Self {
      map: map,
      curr_mode: GameMode::Primary,
      curr_room: Hallway,
      show_desc: true,
    }
  }

  pub fn tick(&mut self) {
    match self.curr_mode {
      GameMode::Primary => {
        if self.show_desc {
          println!("{}", self.map.room(self.curr_room).description);
          self.show_desc = false;
        }

        match PrimaryCommand::get() {
          PrimaryCommand::Go(dir) => {
            if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
              self.curr_room = room;
              self.show_desc = true;
            } else {
              println!("You can't go that way.");
            }
          },
          PrimaryCommand::Look => { self.show_desc = true; }
          PrimaryCommand::Quit => { self.curr_mode = GameMode::Finished; }
        }
      },
      GameMode::Finished => {}
    }
  }
}

fn build_world(map: &mut Map<RoomId>) {
  map.room(Hallway).describe(
    "Hallway",
    "You are in the hallway. \
     There is a door to the south. \
     Through the windows to the north you can see a secret herb garden."
  );

  map.room(AudienceChamber).describe(
    "Audience Chamber",
    "This is the audience chamber. \
     There is a window to the west. By looking to the right \
     through it you can see the entrance to the castle. \
     Doors leave this room to the north, east, and south."
  );

  map.connect(Hallway, South, AudienceChamber);
}

fn main() {
  let mut rooms = [Room::new(); MAX_ROOMS];
  let mut map = Map::new(&mut rooms);

  build_world(&mut map);

  let mut state = GameState::new(&mut map);

  println!("Werewolves and Wanderer\n");

  while state.curr_mode != GameMode::Finished {
    state.tick();
  }

  println!("Farewell.");
}
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name};

fn main() {
    // https://coinmarketcap.com/
    // http://crix.hu-berlin.de/
    let mut response = reqwest::get("https://coinmarketcap.com/").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        .parent()
        .unwrap()
        .find(Name("tr"))
        //.take(10)  */
    {
        println!("{}", node.text());
    }

}<commit_msg>To-Do.<commit_after>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name};

fn main() {
    // https://coinmarketcap.com/
    // http://crix.hu-berlin.de/
    let mut response = reqwest::get("https://coinmarketcap.com/#MXN").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        .parent()
        .unwrap()
        .find(Name("tr"))
        .take(3)
    {
        /*  TODO:
            - Avoid table headers
            - Get coin name.
            - Get coin price.
            - Format and print coin name and price.
        */
        println!("{}", node.text());
    }

}<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::io::{Result as IoResult, Error, ErrorKind};

use futures::{Future, Sink, Stream, Poll, StartSend, AsyncSink, Async};
use futures::stream::{once, Once};
use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use tokio_core::io::{Codec,EasyBuf,Io};
use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde_json::Value;
use serde_json::ser::to_vec;
use serde_json::de::from_slice;
use serde_json::value::{to_value, from_value};

// TODO: Modify the serialize/deserialize so it generates the right JSON

#[derive(Debug, Deserialize)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug, Deserialize)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

fn err_map(e: serde_json::error::Error) -> Error {
    Error::new(ErrorKind::Other, e)
}

struct JsonCodec;

impl Codec for JsonCodec {
    type In = Value;
    type Out = Value;
    fn decode(&mut self, buf: &mut EasyBuf) -> IoResult<Option<Value>> {
        // TODO: Use object boundary instead of newlines
        if let Some(i) = buf.as_slice().iter().position(|&b| b == b'\n') {
            let line = buf.drain_to(i);
            buf.drain_to(1);
            from_slice(line.as_slice()).map(Some).map_err(err_map)
        } else {
            Ok(None)
        }
    }
    fn encode(&mut self, msg: Value, buf: &mut Vec<u8>) -> IoResult<()> {
        *buf = to_vec(&msg).map_err(err_map)?;
        buf.push(b'\n');
        Ok(())
    }
}

pub struct RPCFramed<JsonStream>(JsonStream);

impl<JsonStream> RPCFramed<JsonStream> where
    JsonStream: Stream<Item = Value, Error = Error> + Sink<SinkItem = Value, SinkError = Error>
{
    pub fn new(stream: JsonStream) -> Self {
        RPCFramed(stream)
    }
}

impl<JsonStream> Sink for RPCFramed<JsonStream> where
    JsonStream: Stream<Item = Value, Error = Error> + Sink<SinkItem = Value, SinkError = Error>
{
    type SinkError = Error;
    type SinkItem = Message;
    fn start_send(&mut self, item: Message) -> StartSend<Message, Error> {
        let converted = to_value(&item).map_err(err_map)?;
        match self.0.start_send(converted) {
            Ok(AsyncSink::NotReady(_)) => Ok(AsyncSink::NotReady(item)),
            other => other.map(|_| AsyncSink::Ready),
        }
    }
    fn poll_complete(&mut self) -> Poll<(), Error> {
        self.0.poll_complete()
    }
}

// TODO: Implement some kind of error handling other than just bailing out?
// But that is going to be tricky with the batch where some of the items might error and some not.
impl<JsonStream> Stream for RPCFramed<JsonStream> where
    JsonStream: Stream<Item = Value, Error = Error> + Sink<SinkItem = Value, SinkError = Error>
{
    type Error = Error;
    type Item = Message;
    fn poll(&mut self) -> Poll<Option<Message>, Error> {
        match self.0.poll() {
            Err(e) => Err(e),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
            Ok(Async::Ready(Some(value))) => {
                Ok(Async::Ready(Some(from_value(value).map_err(err_map)?)))
            },
        }
    }
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let listener = TcpListener::bind(&"127.0.0.1:2345".parse().unwrap(), &handle).unwrap();
    let connections = listener.incoming();
    let service = connections.for_each(|(stream, _)| {
        let jsonized = stream.framed(JsonCodec);
        let rpcized = RPCFramed::new(jsonized);
        let (w, r) = rpcized.split();
        let header: Once<_, Error> = once(Ok(Message::Batch(
            vec![
                Message::Request(Request { jsonrpc: Version, method: "Hello".to_owned(), params: Some(Value::Null), id: Value::Bool(true) }),
                Message::Response(Response { result: Ok(Value::Bool(false)), id: Value::Bool(true) }),
                Message::Response(Response { result: Err(RPCError { code: 42, message: "Wrong!".to_owned(), data: None }), id: Value::Null }),
                Message::Notification(Notification { jsonrpc: Version, method: "Alert!".to_owned(), params: Some(Value::String("blabla".to_owned())) }),
                Message::Unmatched(Value::String(String::new())),
            ])));
        let sent = w.send_all(header).and_then(|(sink, _)| sink.send_all(r))
            .map(|_| ())
            .map_err(|_| {
                // TODO Something with the error ‒ logging?
                ()
            });
        // Do the sending in the background
        handle.spawn(sent);
        Ok(())
    });
    core.run(service).unwrap();
}
<commit_msg>Do the serialization directly<commit_after>extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::io::{Result as IoResult, Error, ErrorKind};

use futures::{Future, Sink, Stream};
use futures::stream::{once, Once};
use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use tokio_core::io::{Codec,EasyBuf,Io};
use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde_json::Value;
use serde_json::ser::to_vec;
use serde_json::de::from_slice;

// TODO: Modify the serialize/deserialize so it generates the right JSON

#[derive(Debug, Deserialize)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug, Deserialize)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

fn err_map(e: serde_json::error::Error) -> Error {
    Error::new(ErrorKind::Other, e)
}

struct RPCCodec;

impl Codec for RPCCodec {
    type In = Message;
    type Out = Message;
    fn decode(&mut self, buf: &mut EasyBuf) -> IoResult<Option<Message>> {
        // TODO: Use object boundary instead of newlines
        if let Some(i) = buf.as_slice().iter().position(|&b| b == b'\n') {
            let line = buf.drain_to(i);
            buf.drain_to(1);
            from_slice(line.as_slice()).map(Some).map_err(err_map)
        } else {
            Ok(None)
        }
    }
    fn encode(&mut self, msg: Message, buf: &mut Vec<u8>) -> IoResult<()> {
        *buf = to_vec(&msg).map_err(err_map)?;
        buf.push(b'\n');
        Ok(())
    }
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let listener = TcpListener::bind(&"127.0.0.1:2345".parse().unwrap(), &handle).unwrap();
    let connections = listener.incoming();
    let service = connections.for_each(|(stream, _)| {
        let jsonized = stream.framed(RPCCodec);
        let (w, r) = jsonized.split();
        let header: Once<_, Error> = once(Ok(Message::Batch(
            vec![
                Message::Request(Request { jsonrpc: Version, method: "Hello".to_owned(), params: Some(Value::Null), id: Value::Bool(true) }),
                Message::Response(Response { result: Ok(Value::Bool(false)), id: Value::Bool(true) }),
                Message::Response(Response { result: Err(RPCError { code: 42, message: "Wrong!".to_owned(), data: None }), id: Value::Null }),
                Message::Notification(Notification { jsonrpc: Version, method: "Alert!".to_owned(), params: Some(Value::String("blabla".to_owned())) }),
                Message::Unmatched(Value::String(String::new())),
            ])));
        let sent = w.send_all(header).and_then(|(sink, _)| sink.send_all(r))
            .map(|_| ())
            .map_err(|_| {
                // TODO Something with the error ‒ logging?
                ()
            });
        // Do the sending in the background
        handle.spawn(sent);
        Ok(())
    });
    core.run(service).unwrap();
}
<|endoftext|>


<commit_before>extern crate image;
extern crate time;
extern crate rayon;

extern crate rusttracer;

use std::path::Path;
use std::env;
use std::f64::consts::PI;

use rusttracer::math::{Vector3, Point3, Matrix4, Transform};
use rusttracer::{Scene, Color, Camera, MaterialTemplate, Renderer, SuperSampling};
use rusttracer::geometry::{Plane, Transformable, Intersectable};
use rusttracer::lights::PointLight;
use rusttracer::mesh_loader::MeshLoader;

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 1280;
const HEIGHT: u32 = 800;

fn main() {
    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };
    let template = MaterialTemplate::new(Color::blue() * 0.02,
                                         Color::black(),
                                         Color::black(),
                                         0.0,
                                         None,
                                         None);

    let floor_material = template.build_material(|material| {
                                                     material.ambient_color = Color::white() * 0.05;
                                                     material.diffuse_color = Color::white() * 0.6;
                                                 });
    let floor = Plane::new(Point3::new(0.0, -5.0, 0.0),
                           Vector3::new(0.0, 1.0, 0.0),
                           floor_material);

    let back_material =
        template.build_material(|material| { material.diffuse_color = Color::white() * 0.8; });
    let back = Plane::new(Point3::new(0.0, 0.0, -50.0),
                          Vector3::new(0.0, 0.0, 1.0),
                          back_material);

    let l1 = PointLight::new(Point3::new(0.0, 3.0, -45.0), Color::new(67, 249, 253), 5.0);
    let l2 = PointLight::new(Point3::new(-15.0, 3.0, -45.0), Color::new(92, 253, 67), 5.0);
    let l3 = PointLight::new(Point3::new(15.0, 3.0, -45.0), Color::new(253, 115, 6), 5.0);
    let l4 = PointLight::new(Point3::new(0.0, 10.0, -20.0), Color::white(), 100.0);

    let white_material = template.build_material(|material| {
                                                     material.diffuse_color = Color::white() * 0.6;
                                                     material.specular_color = Color::white();
                                                     material.specular_exponent = 90.0;
                                                     material.reflection_coefficient = Some(0.3);
                                                 });

    let mesh_loader = MeshLoader::new();
    let mut suzanne = mesh_loader.load(Path::new("models/dragon.obj"), &white_material);

    let mut objects: Vec<&Intersectable> = vec![&floor, &back];

    for (index, mesh) in suzanne.iter_mut().enumerate() {
        let transform =
            Transform::new(Matrix4::scale_uniform(10.0) * Matrix4::rot_y(PI / 2.0) *
                           Matrix4::translate(0.0 + (index as f64) * -5.0, -3.0, -40.0));
        mesh.transform(&transform);
        objects.push(mesh as &Intersectable);
    }

    let lights: Vec<&PointLight> = vec![&l1, &l2, &l3, &l4];
    let scene = Scene::new(&objects, &lights, Color::black());
    let camera = Camera::new(0.873,
                             WIDTH,
                             HEIGHT,
                             Point3::new(0.0, 0.0, -30.0),
                             Point3::new(0.0, -3.0, -40.0),
                             Vector3::new(0.0, 1.0, 0.0));

    let renderer = Renderer::new(&scene, &camera, SuperSampling::Off);

    if benchmark {
        for _ in 0..10 {
            let _ = renderer.render(MAX_DEPTH);
        }

        return;
    }

    let buffer = renderer.render(MAX_DEPTH);

    let timestamp = time::get_time().sec;
    let filename = format!("images/{}.png", timestamp);
    image::save_buffer(&Path::new(&filename),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<commit_msg>[Chore] Remove unused crate reference<commit_after>extern crate image;
extern crate time;

extern crate rusttracer;

use std::path::Path;
use std::env;
use std::f64::consts::PI;

use rusttracer::math::{Vector3, Point3, Matrix4, Transform};
use rusttracer::{Scene, Color, Camera, MaterialTemplate, Renderer, SuperSampling};
use rusttracer::geometry::{Plane, Transformable, Intersectable};
use rusttracer::lights::PointLight;
use rusttracer::mesh_loader::MeshLoader;

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 1280;
const HEIGHT: u32 = 800;

fn main() {
    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };
    let template = MaterialTemplate::new(Color::blue() * 0.02,
                                         Color::black(),
                                         Color::black(),
                                         0.0,
                                         None,
                                         None);

    let floor_material = template.build_material(|material| {
                                                     material.ambient_color = Color::white() * 0.05;
                                                     material.diffuse_color = Color::white() * 0.6;
                                                 });
    let floor = Plane::new(Point3::new(0.0, -5.0, 0.0),
                           Vector3::new(0.0, 1.0, 0.0),
                           floor_material);

    let back_material =
        template.build_material(|material| { material.diffuse_color = Color::white() * 0.8; });
    let back = Plane::new(Point3::new(0.0, 0.0, -50.0),
                          Vector3::new(0.0, 0.0, 1.0),
                          back_material);

    let l1 = PointLight::new(Point3::new(0.0, 3.0, -45.0), Color::new(67, 249, 253), 5.0);
    let l2 = PointLight::new(Point3::new(-15.0, 3.0, -45.0), Color::new(92, 253, 67), 5.0);
    let l3 = PointLight::new(Point3::new(15.0, 3.0, -45.0), Color::new(253, 115, 6), 5.0);
    let l4 = PointLight::new(Point3::new(0.0, 10.0, -20.0), Color::white(), 100.0);

    let white_material = template.build_material(|material| {
                                                     material.diffuse_color = Color::white() * 0.6;
                                                     material.specular_color = Color::white();
                                                     material.specular_exponent = 90.0;
                                                     material.reflection_coefficient = Some(0.3);
                                                 });

    let mesh_loader = MeshLoader::new();
    let mut suzanne = mesh_loader.load(Path::new("models/dragon.obj"), &white_material);

    let mut objects: Vec<&Intersectable> = vec![&floor, &back];

    for (index, mesh) in suzanne.iter_mut().enumerate() {
        let transform =
            Transform::new(Matrix4::scale_uniform(10.0) * Matrix4::rot_y(PI / 2.0) *
                           Matrix4::translate(0.0 + (index as f64) * -5.0, -3.0, -40.0));
        mesh.transform(&transform);
        objects.push(mesh as &Intersectable);
    }

    let lights: Vec<&PointLight> = vec![&l1, &l2, &l3, &l4];
    let scene = Scene::new(&objects, &lights, Color::black());
    let camera = Camera::new(0.873,
                             WIDTH,
                             HEIGHT,
                             Point3::new(0.0, 0.0, -30.0),
                             Point3::new(0.0, -3.0, -40.0),
                             Vector3::new(0.0, 1.0, 0.0));

    let renderer = Renderer::new(&scene, &camera, SuperSampling::Off);

    if benchmark {
        for _ in 0..10 {
            let _ = renderer.render(MAX_DEPTH);
        }

        return;
    }

    let buffer = renderer.render(MAX_DEPTH);

    let timestamp = time::get_time().sec;
    let filename = format!("images/{}.png", timestamp);
    image::save_buffer(&Path::new(&filename),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]

#![feature(test)]

extern crate jsrs_common;
extern crate jsrs_parser;
extern crate french_press;

extern crate walkdir;
extern crate unescape;
extern crate rustyline;
extern crate rustc_serialize;
extern crate docopt;

extern crate test;

#[macro_use]
mod var;

mod eval;
mod native;
mod number;
mod bench;
mod preprocess;

use std::cell::RefCell;
use std::fs::{File, metadata};
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use walkdir::WalkDir;

use jsrs_common::types::coerce::AsString;
use french_press::{init_gc, ScopeManager};

use eval::eval_string;
use native::add_pervasives;
use preprocess::{clean_string, add_semicolon};
use jsrs_common::js_error::{self, JsError};

docopt!(Args derive Debug, "
js.rs - a javascript interpreter

Usage:
jsrs
jsrs <file>
jsrs --test
");

fn eval_file(filename: String, debug: bool, should_repl: bool,
             scope_manager: Rc<RefCell<ScopeManager>>) -> js_error::Result<()> {
    if debug {
        println!("Reading from \"{}\"", filename);
    }

    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    // Build lines
    let mut line_builder = String::new();
    let mut braces = Vec::new();
    let mut negative_test = false;

    let mut file_iter = file_buffer.lines();
    while let Some(line) = file_iter.next() {
        let input = String::from(line.expect(&format!("Cannot read from {}", filename)));
        let input = clean_string(input);
        if input.contains("@negative") {
            negative_test = true;
        }

        let mut last = '\0';
        // Match braces to see if we should wait for more input
        for c in input.chars() {
            if c == '(' {
                braces.push('(');
            } else if c == '{' {
                braces.push('{');
            } else if c == '*' && last == '/' {
                braces.push('/');
            } else if c == ')' {
                if braces.pop() != Some('(') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            } else if c == '}' {
                if braces.pop() != Some('{') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            } else if c == '/' && last == '*' {
                if braces.pop() != Some('/') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            }
            last = c;
        }

        line_builder.push_str(&input);

        if braces.len() == 0 {
            let js_string = clean_string(line_builder.clone());
            if js_string == "" {
                continue;
            }

            if debug {
                println!("\n{}", js_string);
            }

            let ret;
            let eval_result = eval_string(&js_string, scope_manager.clone());
            if let Err(JsError::ParseError(_)) = eval_result {
                continue;
            }

            if negative_test {
                match eval_result {
                    Ok((var, ptr)) => ret = (var, ptr),
                    Err(e) => {
                        if !e.is_meta_error() {
                            return Ok(());
                        } else {
                            return Err(e);
                        }
                    }
                }
            } else {
                ret = try!(eval_result);
            }

            if debug {
                println!("=> {:?}", ret);
            }

            // Clear line builder for next statement.
            line_builder = String::new();
        }
    }
    if line_builder != "" {
        let ret;
        let js_string = clean_string(line_builder.clone());
        let eval_result = eval_string(&js_string, scope_manager.clone());

        if negative_test {
            match eval_result {
                Ok((var, ptr)) => ret = (var, ptr),
                Err(e) => {
                    if !e.is_meta_error() {
                        return Ok(());
                    } else {
                        return Err(e);
                    }
                }
            }
        } else {
            ret = try!(eval_result);
        }

        if debug {
            println!("=> {:?}", ret);
        }
    }
    if should_repl {
        repl(scope_manager);
    }
    Ok(())
}

fn test_dir(dir_name: String) {
    for entry in WalkDir::new(dir_name) {
        let entry = entry.unwrap();
        if !entry.path().is_dir() {
            let entry_path = entry.path().display().to_string();
            let scope_manager = Rc::new(RefCell::new(init_gc()));
            add_pervasives(scope_manager.clone());
            println!("{}", entry_path);
            match eval_file(entry_path.clone(), false, false, scope_manager.clone()) {
                Ok(_) => {
                    println!("{}: {}", entry_path, "OK");
                }
                Err(e) => {
                    println!("{}: {}", entry_path, e);
                }
            }
        }
    }
}

fn repl(scope_manager: Rc<RefCell<ScopeManager>>) -> i32 {
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let input = add_semicolon(clean_string(String::from(line)));
                if input == "" {
                    continue;
                }
                rl.add_history_entry(&input);

                match eval_string(&input, scope_manager.clone()) {
                    Ok((var, ptr)) => println!("{}", ptr.map(|p| p.as_string()).unwrap_or(var.t.as_string())),
                    Err(e) => println!("{:?}", e),
                }
            },
            Err(ReadlineError::Interrupted) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 1;
            },
            Err(ReadlineError::Eof) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 3;
            }
        }
    }
    0
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
    if args.flag_test {
        let dir_name = "sputnik";

        test_dir(String::from(dir_name))
    } else {
        let scope_manager = Rc::new(RefCell::new(init_gc()));
        add_pervasives(scope_manager.clone());

        if args.arg_file == "" {
            let ret = repl(scope_manager.clone());
            exit(ret)
        } else {
            eval_file(args.arg_file, true, true, scope_manager.clone())
                .expect("Error evaluating file");
        }
    }
}
<commit_msg>Add space between concatenated file lines<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

#![feature(test)]

extern crate jsrs_common;
extern crate jsrs_parser;
extern crate french_press;

extern crate walkdir;
extern crate unescape;
extern crate rustyline;
extern crate rustc_serialize;
extern crate docopt;

extern crate test;

#[macro_use]
mod var;

mod eval;
mod native;
mod number;
mod bench;
mod preprocess;

use std::cell::RefCell;
use std::fs::{File, metadata};
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use walkdir::WalkDir;

use jsrs_common::types::coerce::AsString;
use french_press::{init_gc, ScopeManager};

use eval::eval_string;
use native::add_pervasives;
use preprocess::{clean_string, add_semicolon};
use jsrs_common::js_error::{self, JsError};

docopt!(Args derive Debug, "
js.rs - a javascript interpreter

Usage:
jsrs
jsrs <file>
jsrs --test
");

fn eval_file(filename: String, debug: bool, should_repl: bool,
             scope_manager: Rc<RefCell<ScopeManager>>) -> js_error::Result<()> {
    if debug {
        println!("Reading from \"{}\"", filename);
    }

    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    // Build lines
    let mut line_builder = String::new();
    let mut braces = Vec::new();
    let mut negative_test = false;

    let mut file_iter = file_buffer.lines();
    while let Some(line) = file_iter.next() {
        let input = String::from(line.expect(&format!("Cannot read from {}", filename)));
        let input = clean_string(input);
        if input.contains("@negative") {
            negative_test = true;
        }

        let mut last = '\0';
        // Match braces to see if we should wait for more input
        for c in input.chars() {
            if c == '(' {
                braces.push('(');
            } else if c == '{' {
                braces.push('{');
            } else if c == '*' && last == '/' {
                braces.push('/');
            } else if c == ')' {
                if braces.pop() != Some('(') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            } else if c == '}' {
                if braces.pop() != Some('{') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            } else if c == '/' && last == '*' {
                if braces.pop() != Some('/') {
                    return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                }
            }
            last = c;
        }

        line_builder.push_str(&input);

        if braces.len() == 0 {
            let js_string = clean_string(line_builder.clone());
            if js_string == "" {
                continue;
            }

            if debug {
                println!("\n{}", js_string);
            }

            let ret;
            let eval_result = eval_string(&js_string, scope_manager.clone());
            if let Err(JsError::ParseError(_)) = eval_result {
                line_builder.push_str(" ");
                continue;
            }

            if negative_test {
                match eval_result {
                    Ok((var, ptr)) => ret = (var, ptr),
                    Err(e) => {
                        if !e.is_meta_error() {
                            return Ok(());
                        } else {
                            return Err(e);
                        }
                    }
                }
            } else {
                ret = try!(eval_result);
            }

            if debug {
                println!("=> {:?}", ret);
            }

            // Clear line builder for next statement.
            line_builder = String::new();
        }
    }
    if line_builder != "" {
        let ret;
        let js_string = clean_string(line_builder.clone());
        let eval_result = eval_string(&js_string, scope_manager.clone());

        if negative_test {
            match eval_result {
                Ok((var, ptr)) => ret = (var, ptr),
                Err(e) => {
                    if !e.is_meta_error() {
                        return Ok(());
                    } else {
                        return Err(e);
                    }
                }
            }
        } else {
            ret = try!(eval_result);
        }

        if debug {
            println!("=> {:?}", ret);
        }
    }
    if should_repl {
        repl(scope_manager);
    }
    Ok(())
}

fn test_dir(dir_name: String) {
    for entry in WalkDir::new(dir_name) {
        let entry = entry.unwrap();
        if !entry.path().is_dir() {
            let entry_path = entry.path().display().to_string();
            let scope_manager = Rc::new(RefCell::new(init_gc()));
            add_pervasives(scope_manager.clone());
            println!("{}", entry_path);
            match eval_file(entry_path.clone(), false, false, scope_manager.clone()) {
                Ok(_) => {
                    println!("{}: {}", entry_path, "OK");
                }
                Err(e) => {
                    println!("{}: {}", entry_path, e);
                }
            }
        }
    }
}

fn repl(scope_manager: Rc<RefCell<ScopeManager>>) -> i32 {
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let input = add_semicolon(clean_string(String::from(line)));
                if input == "" {
                    continue;
                }
                rl.add_history_entry(&input);

                match eval_string(&input, scope_manager.clone()) {
                    Ok((var, ptr)) => println!("{}", ptr.map(|p| p.as_string()).unwrap_or(var.t.as_string())),
                    Err(e) => println!("{:?}", e),
                }
            },
            Err(ReadlineError::Interrupted) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 1;
            },
            Err(ReadlineError::Eof) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 3;
            }
        }
    }
    0
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
    if args.flag_test {
        let dir_name = "sputnik";

        test_dir(String::from(dir_name))
    } else {
        let scope_manager = Rc::new(RefCell::new(init_gc()));
        add_pervasives(scope_manager.clone());

        if args.arg_file == "" {
            let ret = repl(scope_manager.clone());
            exit(ret)
        } else {
            eval_file(args.arg_file, true, true, scope_manager.clone())
                .expect("Error evaluating file");
        }
    }
}
<|endoftext|>


<commit_before>extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: uint = 800;
static HEIGHT: uint = 600;

/// Trial of how we might do the render target stuff.
/// Threads are each sent a send end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the framebuffer
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::Uniform::new(queue.block_dim());
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(px);
                if let Some(hit) = scene.instance.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit);
                    samples.push((px.0, px.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Hand the workers their own send endpoints to communicate results back
/// to the main thread but drop the sender on the main thread so once
/// all threads finish the channel closes
fn spawn_workers(pool: &TaskPool, n: uint, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    for _ in range(0, n) {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render in the scene in parallel to the passed render target
fn render_parallel(rt: &mut film::RenderTarget){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

fn main() {
    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let d = Duration::span(|| render_parallel(&mut rt));
    println!("Rendering took {}ms", d.num_milliseconds());
    film::write_ppm("out.ppm", WIDTH, HEIGHT, rt.get_render().as_slice());
}

<commit_msg>Cleaning up some comments on how the parallel rendering works<commit_after>extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: uint = 800;
static HEIGHT: uint = 600;

/// Threads are each sent a sender end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the render target
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::Uniform::new(queue.block_dim());
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(px);
                if let Some(hit) = scene.instance.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit);
                    samples.push((px.0, px.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Spawn `n` worker threads to render the scene in parallel. Returns the receive end
/// of the channel where the threads will write their samples so that the receiver
/// can write these samples to the render target
fn spawn_workers(pool: &TaskPool, n: uint, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    for _ in range(0, n) {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render in the scene in parallel to the render target
fn render_parallel(rt: &mut film::RenderTarget){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

fn main() {
    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let d = Duration::span(|| render_parallel(&mut rt));
    println!("Rendering took {}ms", d.num_milliseconds());
    film::write_ppm("out.ppm", WIDTH, HEIGHT, rt.get_render().as_slice());
}

<|endoftext|>