<commit_before>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::Handlebars;
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: String,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value::to_value(&value)
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    /// #[Deprecated], for backward compaitibility only
    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::from2(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from2(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(feat) added API Template::with<commit_after>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None
        }
    }

    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string())
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value::to_value(&value),
            content: None
        }
    }

    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string())
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    /// #[Deprecated], for backward compaitibility only
    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::from2(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from2(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                if let Some(ref name) = h.name {
                    return Some(hbs.render(name, &h.value).map_err(TemplateRenderError::from));
                } else if let Some(ref content) = h.content {
                    return Some(hbs.template_render(content, &h.value));
                } else {
                    unreachable!();
                }
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>use ::inflector::Inflector;
use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::parameter;
use infer::TokensResult;

const METHODS: &'static [&'static str] = &[
    "DELETE",
    "GET",
    "HEAD",
    "PATCH",
    "POST",
    "PUT",
];

pub(super) fn valid(method: &str) -> bool {
    METHODS.contains(&method.to_uppercase().as_str())
}

fn fn_ident(method: &str) -> Ident {
    assert!(valid(method), "Invalid method: {}", method);
    Ident::new(method.to_lowercase())
}

fn query_param_struct_ident(method: &str) -> Ident {
    assert!(valid(method), "Invalid method: {}", method);
    Ident::new(format!("{}QueryParams", method.to_class_case()))
}

pub(super) fn infer_v3(method: &str, schema: &Yaml) -> TokensResult {
    let method_fn = fn_ident(&method);
    let query_param_st = query_param_struct_ident(&method);

    let query_params: Vec<(Tokens, Tokens)>;
    let signature: Tokens;
    if let Some(parameters) = schema["parameters"].as_vec() {
        query_params = parameters.iter()
            .filter(|p| p["in"] == Yaml::from_str("query"))
            .map(|p| parameter::infer_v3(p).unwrap())
            .collect();
        signature = quote!{ query_parameters: &#query_param_st };
    } else {
        query_params = Vec::new();
        signature = quote!{};
    }

    let (query_param_fields, query_param_types): (Vec<Tokens>, Vec<Tokens>) = (
        query_params.iter().cloned().map(|(p, _)| p).collect(),
        query_params.iter().cloned().map(|(_, t)| t).collect(),
    );
    let query_param_strings: Vec<Tokens> = query_param_fields.iter().cloned()
        .map(|p| quote!{ "#p" }).collect();
    let query_param_accessors: Vec<Tokens> = query_param_fields.iter().cloned()
        .map(|f| quote!{ query_parameters.#f }).collect();

    Ok(quote! {
        type Response = ();

        #[allow(dead_code)]
        pub(in super::super) struct #query_param_st {
            #(pub(in super::super) #query_param_fields: #query_param_types),*
        }

        #[allow(dead_code)]
        pub(in super::super) fn #method_fn(#signature) -> Response {
            let mut url = tapioca::Url::parse(self::API_URL)
                .expect("Malformed server URL or path.");
            url.set_path(self::API_PATH);
            url.query_pairs_mut()
                .clear()
                #(.append_pair(
                    #query_param_strings,
                    #query_param_accessors.to_string().as_str()
                ))*
                ;

            let client = tapioca::Client::new().unwrap();
            client.#method_fn(url).send();
        }
    })
}
<commit_msg>Avoid needless unit structs when no query params<commit_after>use ::inflector::Inflector;
use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::parameter;
use infer::TokensResult;

const METHODS: &'static [&'static str] = &[
    "DELETE",
    "GET",
    "HEAD",
    "PATCH",
    "POST",
    "PUT",
];

pub(super) fn valid(method: &str) -> bool {
    METHODS.contains(&method.to_uppercase().as_str())
}

fn fn_ident(method: &str) -> Ident {
    assert!(valid(method), "Invalid method: {}", method);
    Ident::new(method.to_lowercase())
}

fn query_param_struct_ident(method: &str) -> Ident {
    assert!(valid(method), "Invalid method: {}", method);
    Ident::new(format!("{}QueryParams", method.to_class_case()))
}

pub(super) fn infer_v3(method: &str, schema: &Yaml) -> TokensResult {
    let method_fn = fn_ident(&method);

    let mut query_param_setter_bb = Tokens::new();
    let mut query_param_st = Tokens::new();
    let mut signature = Tokens::new();

    if let Some(parameters) = schema["parameters"].as_vec() {
        let query_param_st_ident = query_param_struct_ident(&method);
        let query_params: Vec<(Tokens, Tokens)> = parameters.iter()
            .filter(|p| p["in"] == Yaml::from_str("query"))
            .map(|p| parameter::infer_v3(p).unwrap())
            .collect();

        let (query_param_fields, query_param_types): (Vec<Tokens>, Vec<Tokens>) = (
            query_params.iter().cloned().map(|(p, _)| p).collect(),
            query_params.iter().cloned().map(|(_, t)| t).collect(),
        );
        let query_param_accessors: Vec<Tokens> = query_param_fields.iter().cloned()
            .map(|f| quote!{ query_parameters.#f }).collect();
        let query_param_strings: Vec<Tokens> = query_param_fields.iter().cloned()
            .map(|p| quote!{ "#p" }).collect();

        query_param_st = quote! {
            #[allow(dead_code)]
            pub(in super::super) struct #query_param_st_ident {
                #(pub(in super::super) #query_param_fields: #query_param_types),*
            }
        };
        query_param_setter_bb = quote! {
            url.query_pairs_mut()
                .clear()
                #(.append_pair(
                    #query_param_strings,
                    #query_param_accessors.to_string().as_str()
                ))*
                ;
        };
        signature = quote!{ query_parameters: &#query_param_st_ident };
    }

    Ok(quote! {
        type Response = ();

        #query_param_st

        #[allow(dead_code)]
        pub(in super::super) fn #method_fn(#signature) -> Response {
            let mut url = tapioca::Url::parse(self::API_URL)
                .expect("Malformed server URL or path.");
            url.set_path(self::API_PATH);
            #query_param_setter_bb

            let client = tapioca::Client::new().unwrap();
            client.#method_fn(url).send();
        }
    })
}
<|endoftext|>


<commit_before>macro_rules! push {
    ($s:ident, $t:expr) => {{
        // println!("parser push: {:?}", $t);
        Ok($s.vm.borrow_mut().alloc($t))
    }}
}

mod error;

use std::rc::Rc;
use std::cell::RefCell;
use core::*;
use lexer::*;
use self::error::Error;
use self::TokenState::*;

const UNIT_INDX: usize = 0;
const K: usize = 3;

#[derive(Eq, PartialEq, Clone, Debug)]
pub enum TokenState {
    SOT, // Start Of Tokens
    Has(Tokn),
    EOT, // End Of Tokens
}

impl Default for TokenState {
    fn default() -> Self { SOT }
}

pub struct Parser<'a> {
    lexer: Lexer<'a, 'a>,
    vm: Rc<RefCell<Heliqs>>,
    // state: State,
    // current_token: RefCell<TokenState>,
    // aexp_tokens: Vec<Vec<Tokn>>,

    lookahead: [TokenState; K],
    p: usize,
}

impl<'a> Parser<'a> {
    pub fn new(lexer: Lexer<'a, 'a>, vm: Rc<RefCell<Heliqs>>) -> Self {
        let mut parser = Parser {
            lexer: lexer,
            vm: vm,
            // state: State::Aexp,
            // current_token: RefCell::new(SOT),
            // aexp_tokens: vec![vec![]],
            lookahead: Default::default(),
            p: 0,
        };

        for _ in 0..K {
            parser.consume_token();
        }

        parser
    }

    pub fn parse(&mut self) {
        self.add_unit();

        self.add_prim("decr");
        self.add_prim("ltoreq");
        self.add_prim("eq");
        self.add_prim("plus");
        self.add_prim("minus");

        self.add_prim("print");
        self.add_prim("concat");

        match self.parse_aexp() {
            Ok(_) => {},
            Err(e) => {
                println!("parse error: {:?}", e);
            },
        }
    }

    fn parse_aexp(&mut self) -> Result<usize, Error> {
        self.log("parse_aexp");
        match self.current_token() {
            Has(Tokn::Sgqt) => self.parse_tpiq_single(),
            Has(Tokn::Pipe) => self.parse_tpiq(),
            Has(Tokn::Crrt) => self.parse_mpiq(),
            _ => {
                let l = (self.parse_expression())?;
                match self.current_token() {
                    Has(Tokn::Coln) => self.parse_cons(l),
                    _ => Ok(l),
                }
            },
        }
    }

    fn parse_tpiq_single(&mut self) -> Result<usize, Error> {
        self.log("parse_tpiq_single");
        self.consume_token(); // dispatcher Sgqtのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                // 引数は一つ、それをqとみなす
                let qidx = (self.parse_aexp())?;
                self.match_otag(UNIT_INDX, qidx, otag)
            },
            t @ _ => Err(Error::TpiqSingle(t)),
        }
    }

    fn parse_tpiq(&mut self) -> Result<usize, Error> {
        self.log("parse_tpiq");
        self.consume_token(); // dispatcher Pipeのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_aexp())?;
                self.match_otag(pidx, qidx, otag)
            },
            Has(Tokn::Pipe) => {
                // Pipeなのに引数は一つだけという、特殊なパターンになるが一度試す
                self.consume_token();
                let qidx = (self.parse_aexp())?;
                push!(self, Epiq::Quot(UNIT_INDX, qidx))
            },
            _ => panic!("parse_tpiq {:?}はOtag/Pipeではありません", self.current_token()),
        }
    }

    fn parse_mpiq(&mut self) -> Result<usize, Error> {
        self.consume_token(); // dispatcher Crrtのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                match otag.as_ref() {
                    // ^Tと^Fは特別扱い
                    "T" => push!(self, Epiq::Tval),
                    "F" => push!(self, Epiq::Fval),
                    _ => {
                        let pidx = (self.parse_aexp())?;
                        let qidx = (self.parse_aexp())?;
                        push!(self, Epiq::Mpiq{o: otag.clone(), p: pidx, q: qidx})
                    },
                }
            },
            Has(Tokn::Lbkt) => {
                let pidx = self.vm.borrow_mut().alloc(Epiq::Uit8(-1));
                let qidx = (self.parse_list())?;
                push!(self, Epiq::Mpiq{o:">".to_string(), p: pidx, q: qidx })
            },
            _ => panic!("parse_mpiq {:?}がOtag/Lbktではありません", self.current_token()) /*Err(Error::Unimplemented)*/,
        }
    }

    fn match_otag(&mut self, pidx: NodeId, qidx: NodeId, otag: &str) -> Result<usize, Error> {
        match otag {
            ">" => push!(self, Epiq::Eval(pidx, qidx)),
            ":" => push!(self, Epiq::Lpiq(pidx, qidx)),
            "!" => push!(self, Epiq::Appl(pidx, qidx)),
            "@" => push!(self, Epiq::Rslv(pidx, qidx)),
            "?" => push!(self, Epiq::Cond(pidx, qidx)),
            "%" => push!(self, Epiq::Envn(pidx, qidx)),
            "#" => push!(self, Epiq::Bind(pidx, qidx)),
            "." => push!(self, Epiq::Accs(pidx, qidx)),
            r"\" => push!(self, Epiq::Lmbd(pidx, qidx)),
            _ => push!(self, Epiq::Tpiq{o: otag.to_string(), p: pidx, q: qidx}),
        }
    }

    fn parse_cons(&mut self, pidx: usize) -> Result<usize, Error> {
        self.log("parse_cons");
        self.consume_token(); // Coln
        // aexpではない、あえてexpressionしか入れられないように
        // 中置記法の使い方を限定する
        let qidx = (self.parse_expression())?;
        match self.current_token() {
            Has(Tokn::Coln) => {
                let new_cons = (self.parse_cons(qidx))?;
                push!(self, Epiq::Lpiq(pidx, new_cons))
            },
            _ => push!(self, Epiq::Lpiq(pidx, qidx)),
        }
    }

    // expressionとは、ここでは中置記法の中の値になれるものを指している
    fn parse_expression(&mut self) -> Result<usize, Error> {
        self.log("parse_expression");
        // ここはcomsume_tokenしない
        match self.current_token() {
            Has(Tokn::Lbkt) => self.parse_list(),
            _ => {
                let l = (self.parse_accessing_term())?;
                match self.current_token() {
                    Has(Tokn::Bang) => self.parse_apply(l),
                    _ => Ok(l),
                }
            }
        }
    }

    fn parse_list(&mut self) -> Result<usize, Error> {
        self.log("parse_list");
        self.consume_token();
        self.parse_list_internal()
    }

    fn parse_list_internal(&mut self) -> Result<usize, Error> {
        self.log("parse_list_internal");
        // 閉じbracketが出るまで再帰呼出
        match self.current_token() {
            Has(Tokn::Rbkt) => {
                self.consume_token();
                push!(self, Epiq::Unit)
            },
            _ => {
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_list_internal())?;
                push!(self, Epiq::Lpiq(pidx, qidx))
            }
        }
    }

    fn parse_accessing_term(&mut self) -> Result<usize, Error> {
        self.log("parse_accessing_term");
        let l = (self.parse_term())?;
        match self.current_token() {
            Has(Tokn::Stop) => self.parse_accessor(l),
            _ => Ok(l),
        }
    }

    fn parse_accessor(&mut self, left: usize) -> Result<usize, Error> {
        self.log("parse_accessor");
        self.consume_token();
        let qidx = (self.parse_term())?; // TODO: 左側はexpressionにしたいが一旦保留
        match self.current_token() {
            Has(Tokn::Stop) => {
                let id = self.vm.borrow_mut().alloc(Epiq::Accs(left, qidx));
                let new_left = self.vm.borrow_mut().alloc(Epiq::Eval(UNIT_INDX, id));
                let new_cons = (self.parse_accessor(new_left))?;
                push!(self, Epiq::Eval(UNIT_INDX, new_cons))
            },
            _ => {
                let id = self.vm.borrow_mut().alloc(Epiq::Accs(left, qidx));
                push!(self, Epiq::Eval(UNIT_INDX, id))
            },
        }
    }

    /// "term" means resolve or literal in this context
    fn parse_term(&mut self) -> Result<usize, Error> {
        self.log("parse_term");
        match self.current_token() {
            Has(Tokn::Atsm) => self.parse_resolve(),
            _ => self.parse_literal(),
        }
    }

    fn parse_apply(&mut self, left: usize) -> Result<usize, Error> {
        self.consume_token();
        let qidx = (self.parse_expression())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Appl(left, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    fn parse_resolve(&mut self) -> Result<usize, Error> {
        self.consume_token(); // Atsm
        let qidx = (self.parse_literal())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Rslv(UNIT_INDX, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    fn parse_literal(&mut self) -> Result<usize, Error> {
        self.log("parse_literal");
        match self.current_token() {
            Has(Tokn::Smcl) => self.parse_unit(),
            Has(Tokn::Dbqt) => self.parse_text(),
            Has(Tokn::Chvc(ref s)) => self.parse_name(s),
            Has(Tokn::Nmbr(ref s)) => self.parse_number(s),
            _ => panic!("parse_literal {:?}がSmcl/Dbqt/Chvc/Nmbrではありません", self.current_token())/*Err(Error::Unimplemented)*/,
        }
    }

    fn parse_unit(&mut self) -> Result<usize, Error> {
        self.log("parse_unit");
        self.consume_token(); // Smclのはず
        self.vm.borrow_mut().set_entry(UNIT_INDX); // これをしないと;だけの時にentrypointがダメになる
        Ok(UNIT_INDX)
    }

    fn parse_text(&mut self) -> Result<usize, Error> {
        self.consume_token(); // Dbqt
        if let Has(Tokn::Chvc(ref s)) = self.current_token() {
            self.consume_token();
            if let Has(Tokn::Dbqt) = self.current_token() {
                self.consume_token();
                push!(self, Epiq::Text(s.clone()))
            } else {
                Err(Error::Unimplemented)
            }
        } else {
            Err(Error::Unimplemented)
        }
    }

    fn parse_name(&mut self, s: &str) -> Result<usize, Error> {
        self.log("parse_name");
        self.consume_token();
        push!(self, Epiq::Name(s.to_string()))
    }

    fn parse_number(&mut self, s: &str) -> Result<usize, Error> {
        self.consume_token();
        push!(self, Epiq::Uit8(s.parse::<i64>().unwrap()))
    }

    // Unitは常に1つにする(index固定)
    fn add_unit(&mut self) {
        let _unit = self.vm.borrow_mut().alloc(Epiq::Unit);
    }

    fn add_prim(&mut self, name: &str) {
        let prim = self.vm.borrow_mut().alloc(Epiq::Prim(name.to_string()));
        log(format!("add_prim: {:?} {:?}", name, prim));
        self.vm.borrow_mut().define(name, prim);
    }

    fn consume_token(&mut self) {
        let res = self.lexer.tokenize();
        match res {
            TokenizeResult::Ok(t) => self.set_current_token(Has(t)),
            TokenizeResult::Err(_e) => {},
            TokenizeResult::EOF => self.set_current_token(EOT),
        }
    }

    fn set_current_token(&mut self, t: TokenState) {
        self.lookahead[self.p] = t;
        self.p = (self.p + 1) % K;
    }

    fn token(&self, i: usize) -> TokenState {
        self.lookahead[(self.p + i) % K].clone()
    }

    fn current_token(&self) -> TokenState {
        self.token(0)
    }

    fn log(&self, func_name: &str) {
        if false {
            println!("{}: {:?}", func_name, self.current_token());
        }
    }
}
<commit_msg>add feature about ^[] read macro<commit_after>macro_rules! push {
    ($s:ident, $t:expr) => {{
        // println!("parser push: {:?}", $t);
        Ok($s.vm.borrow_mut().alloc($t))
    }}
}

mod error;

use std::rc::Rc;
use std::cell::RefCell;
use core::*;
use lexer::*;
use self::error::Error;
use self::TokenState::*;

const UNIT_INDX: usize = 0;
const K: usize = 3;

#[derive(Eq, PartialEq, Clone, Debug)]
pub enum TokenState {
    SOT, // Start Of Tokens
    Has(Tokn),
    EOT, // End Of Tokens
}

impl Default for TokenState {
    fn default() -> Self { SOT }
}

pub struct Parser<'a> {
    lexer: Lexer<'a, 'a>,
    vm: Rc<RefCell<Heliqs>>,
    // state: State,
    // current_token: RefCell<TokenState>,
    // aexp_tokens: Vec<Vec<Tokn>>,

    lookahead: [TokenState; K],
    p: usize,
}

impl<'a> Parser<'a> {
    pub fn new(lexer: Lexer<'a, 'a>, vm: Rc<RefCell<Heliqs>>) -> Self {
        let mut parser = Parser {
            lexer: lexer,
            vm: vm,
            // state: State::Aexp,
            // current_token: RefCell::new(SOT),
            // aexp_tokens: vec![vec![]],
            lookahead: Default::default(),
            p: 0,
        };

        for _ in 0..K {
            parser.consume_token();
        }

        parser
    }

    pub fn parse(&mut self) {
        self.add_unit();

        self.add_prim("decr");
        self.add_prim("ltoreq");
        self.add_prim("eq");
        self.add_prim("plus");
        self.add_prim("minus");

        self.add_prim("print");
        self.add_prim("concat");

        match self.parse_aexp() {
            Ok(_) => {},
            Err(e) => {
                println!("parse error: {:?}", e);
            },
        }
    }

    fn parse_aexp(&mut self) -> Result<usize, Error> {
        self.log("parse_aexp");
        match self.current_token() {
            Has(Tokn::Sgqt) => self.parse_tpiq_single(),
            Has(Tokn::Pipe) => self.parse_tpiq(),
            Has(Tokn::Crrt) => self.parse_mpiq(),
            _ => {
                let l = (self.parse_expression())?;
                match self.current_token() {
                    Has(Tokn::Coln) => self.parse_cons(l),
                    _ => Ok(l),
                }
            },
        }
    }

    fn parse_tpiq_single(&mut self) -> Result<usize, Error> {
        self.log("parse_tpiq_single");
        self.consume_token(); // dispatcher Sgqtのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                // 引数は一つ、それをqとみなす
                let qidx = (self.parse_aexp())?;
                self.match_otag(UNIT_INDX, qidx, otag)
            },
            t @ _ => Err(Error::TpiqSingle(t)),
        }
    }

    fn parse_tpiq(&mut self) -> Result<usize, Error> {
        self.log("parse_tpiq");
        self.consume_token(); // dispatcher Pipeのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_aexp())?;
                self.match_otag(pidx, qidx, otag)
            },
            Has(Tokn::Pipe) => {
                // Pipeなのに引数は一つだけという、特殊なパターンになるが一度試す
                self.consume_token();
                let qidx = (self.parse_aexp())?;
                push!(self, Epiq::Quot(UNIT_INDX, qidx))
            },
            _ => panic!("parse_tpiq {:?}はOtag/Pipeではありません", self.current_token()),
        }
    }

    fn parse_mpiq(&mut self) -> Result<usize, Error> {
        self.consume_token(); // dispatcher Crrtのはず
        match self.current_token() {
            Has(Tokn::Otag(ref otag)) => {
                self.consume_token();
                match otag.as_ref() {
                    // ^Tと^Fは特別扱い
                    "T" => push!(self, Epiq::Tval),
                    "F" => push!(self, Epiq::Fval),
                    _ => {
                        let pidx = (self.parse_aexp())?;
                        let qidx = (self.parse_aexp())?;
                        push!(self, Epiq::Mpiq{o: otag.clone(), p: pidx, q: qidx})
                    },
                }
            },
            Has(Tokn::Lbkt) => {
                let pidx = UNIT_INDX; //self.vm.borrow_mut().alloc(Epiq::Uit8(-1));
                let qidx = (self.parse_list())?;
                push!(self, Epiq::Mpiq{o:">".to_string(), p: pidx, q: qidx })
            },
            _ => panic!("parse_mpiq {:?}がOtag/Lbktではありません", self.current_token()) /*Err(Error::Unimplemented)*/,
        }
    }

    fn match_otag(&mut self, pidx: NodeId, qidx: NodeId, otag: &str) -> Result<usize, Error> {
        match otag {
            ">" => push!(self, Epiq::Eval(pidx, qidx)),
            ":" => push!(self, Epiq::Lpiq(pidx, qidx)),
            "!" => push!(self, Epiq::Appl(pidx, qidx)),
            "@" => push!(self, Epiq::Rslv(pidx, qidx)),
            "?" => push!(self, Epiq::Cond(pidx, qidx)),
            "%" => push!(self, Epiq::Envn(pidx, qidx)),
            "#" => push!(self, Epiq::Bind(pidx, qidx)),
            "." => push!(self, Epiq::Accs(pidx, qidx)),
            r"\" => push!(self, Epiq::Lmbd(pidx, qidx)),
            _ => push!(self, Epiq::Tpiq{o: otag.to_string(), p: pidx, q: qidx}),
        }
    }

    fn parse_cons(&mut self, pidx: usize) -> Result<usize, Error> {
        self.log("parse_cons");
        self.consume_token(); // Coln
        // aexpではない、あえてexpressionしか入れられないように
        // 中置記法の使い方を限定する
        let qidx = (self.parse_expression())?;
        match self.current_token() {
            Has(Tokn::Coln) => {
                let new_cons = (self.parse_cons(qidx))?;
                push!(self, Epiq::Lpiq(pidx, new_cons))
            },
            _ => push!(self, Epiq::Lpiq(pidx, qidx)),
        }
    }

    // expressionとは、ここでは中置記法の中の値になれるものを指している
    fn parse_expression(&mut self) -> Result<usize, Error> {
        self.log("parse_expression");
        // ここはcomsume_tokenしない
        match self.current_token() {
            Has(Tokn::Lbkt) => self.parse_list(),
            Has(Tokn::Crrt) => self.parse_mpiq(),
            _ => {
                let l = (self.parse_accessing_term())?;
                match self.current_token() {
                    Has(Tokn::Bang) => self.parse_apply(l),
                    _ => Ok(l),
                }
            }
        }
    }

    fn parse_list(&mut self) -> Result<usize, Error> {
        self.log("parse_list");
        self.consume_token();
        self.parse_list_internal()
    }

    fn parse_list_internal(&mut self) -> Result<usize, Error> {
        self.log("parse_list_internal");
        // 閉じbracketが出るまで再帰呼出
        match self.current_token() {
            Has(Tokn::Rbkt) => {
                self.consume_token();
                push!(self, Epiq::Unit)
            },
            _ => {
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_list_internal())?;
                push!(self, Epiq::Lpiq(pidx, qidx))
            }
        }
    }

    fn parse_accessing_term(&mut self) -> Result<usize, Error> {
        self.log("parse_accessing_term");
        let l = (self.parse_term())?;
        match self.current_token() {
            Has(Tokn::Stop) => self.parse_accessor(l),
            _ => Ok(l),
        }
    }

    fn parse_accessor(&mut self, left: usize) -> Result<usize, Error> {
        self.log("parse_accessor");
        self.consume_token();
        let qidx = (self.parse_term())?; // TODO: 左側はexpressionにしたいが一旦保留
        match self.current_token() {
            Has(Tokn::Stop) => {
                let id = self.vm.borrow_mut().alloc(Epiq::Accs(left, qidx));
                let new_left = self.vm.borrow_mut().alloc(Epiq::Eval(UNIT_INDX, id));
                let new_cons = (self.parse_accessor(new_left))?;
                push!(self, Epiq::Eval(UNIT_INDX, new_cons))
            },
            _ => {
                let id = self.vm.borrow_mut().alloc(Epiq::Accs(left, qidx));
                push!(self, Epiq::Eval(UNIT_INDX, id))
            },
        }
    }

    /// "term" means resolve or literal in this context
    fn parse_term(&mut self) -> Result<usize, Error> {
        self.log("parse_term");
        match self.current_token() {
            Has(Tokn::Atsm) => self.parse_resolve(),
            _ => self.parse_literal(),
        }
    }

    fn parse_apply(&mut self, left: usize) -> Result<usize, Error> {
        self.consume_token();
        let qidx = (self.parse_expression())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Appl(left, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    fn parse_resolve(&mut self) -> Result<usize, Error> {
        self.consume_token(); // Atsm
        let qidx = (self.parse_literal())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Rslv(UNIT_INDX, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    fn parse_literal(&mut self) -> Result<usize, Error> {
        self.log("parse_literal");
        match self.current_token() {
            Has(Tokn::Smcl) => self.parse_unit(),
            Has(Tokn::Dbqt) => self.parse_text(),
            Has(Tokn::Chvc(ref s)) => self.parse_name(s),
            Has(Tokn::Nmbr(ref s)) => self.parse_number(s),
            _ => panic!("parse_literal {:?}がSmcl/Dbqt/Chvc/Nmbrではありません", self.current_token())/*Err(Error::Unimplemented)*/,
        }
    }

    fn parse_unit(&mut self) -> Result<usize, Error> {
        self.log("parse_unit");
        self.consume_token(); // Smclのはず
        self.vm.borrow_mut().set_entry(UNIT_INDX); // これをしないと;だけの時にentrypointがダメになる
        Ok(UNIT_INDX)
    }

    fn parse_text(&mut self) -> Result<usize, Error> {
        self.consume_token(); // Dbqt
        if let Has(Tokn::Chvc(ref s)) = self.current_token() {
            self.consume_token();
            if let Has(Tokn::Dbqt) = self.current_token() {
                self.consume_token();
                push!(self, Epiq::Text(s.clone()))
            } else {
                Err(Error::Unimplemented)
            }
        } else {
            Err(Error::Unimplemented)
        }
    }

    fn parse_name(&mut self, s: &str) -> Result<usize, Error> {
        self.log("parse_name");
        self.consume_token();
        push!(self, Epiq::Name(s.to_string()))
    }

    fn parse_number(&mut self, s: &str) -> Result<usize, Error> {
        self.consume_token();
        push!(self, Epiq::Uit8(s.parse::<i64>().unwrap()))
    }

    // Unitは常に1つにする(index固定)
    fn add_unit(&mut self) {
        let _unit = self.vm.borrow_mut().alloc(Epiq::Unit);
    }

    fn add_prim(&mut self, name: &str) {
        let prim = self.vm.borrow_mut().alloc(Epiq::Prim(name.to_string()));
        log(format!("add_prim: {:?} {:?}", name, prim));
        self.vm.borrow_mut().define(name, prim);
    }

    fn consume_token(&mut self) {
        let res = self.lexer.tokenize();
        match res {
            TokenizeResult::Ok(t) => self.set_current_token(Has(t)),
            TokenizeResult::Err(_e) => {},
            TokenizeResult::EOF => self.set_current_token(EOT),
        }
    }

    fn set_current_token(&mut self, t: TokenState) {
        self.lookahead[self.p] = t;
        self.p = (self.p + 1) % K;
    }

    fn token(&self, i: usize) -> TokenState {
        self.lookahead[(self.p + i) % K].clone()
    }

    fn current_token(&self) -> TokenState {
        self.token(0)
    }

    fn log(&self, func_name: &str) {
        if false {
            println!("{}: {:?}", func_name, self.current_token());
        }
    }
}
<|endoftext|>


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

//! # Command Parser
//!
//! The command parser deals with interpreting textual input (like a
//! command line) and executing a command with the provided parameters.
//!
//! Each command has a name which is typically a series of words. Some
//! examples might be:
//!
//! * `show directory /bin`
//! * `show struct`
//! * `thread step in`
//! * `thread step out`
//! * `show process list`
//!
//! Don't worry about commands being long. Ideally, it will be rare that
//! that the entire command would be typed by applying intelligent and
//! interactive autocompletion.
//!
//! Commands can take parameters. Parameters can be marked as `required`
//! or `repeatable`. Repeatable parameters generate a list of values
//! rather than a single value.
//!
//! There are [three kinds of parameters]:
//!
//! * Simple: Just a value that is present in the command line. For
//!   example: `show interface eth0` where `eth0` is a simple
//!   parameter `name` which will have the value `eth0`.
//! * Named: A name that precedes the value in the command line. For
//!   example: `show route src <ip> dst <ip>` where `src <ip>` and
//!   `dst <ip>` are both named parameters to a command `show route`.
//! * Flag: Signify a `true` value when present. For example:
//!   `show log verbose` where `verbose` is a flag parameter that
//!   results in value of `true` when present and `false` when not.
//!
//! The command parser does not assume anything about the implementation
//! of the textual interface. It provides a mechanism for parsing tokens
//! that have been tokenized from an input and a method for communicating
//! with the embedding application for errors and autocompletion by way of
//! using structured data rather than printing to an output device (like
//! `stdout`).
//!
//! The command parser consists of two important things:
//!
//! * A tree that represents the available commands and their arguments.
//!   This tree consists of instances of implementations of [`Node`] like
//!   [`CommandNode`], [`ParameterNode`] and [`RootNode`]. Construction of this
//!   tree is done with the help of [`CommandTree`], [`Command`] and
//!   [`Parameter`].
//! * A [`Parser`] that handles input and matches it against the command
//!   tree. This parser is intended to be short-lived and to just live
//!   for the duration of parsing and evaluating a single command line
//!   input.
//!
//! ## Building A Command Tree
//!
//! The commands handled by a [`Parser`] are represented by a tree based
//! the words in the commands. For example, with commands `show directory`,
//! `show class`, `help`, and `thread step`, there are 3 leaf nodes from
//! the root and the tree is arranged like:
//!
//! * show
//!   * directory
//!   * class
//! * help
//! * thread
//!   * step
//!
//! Building a tree of nodes for use with the parser is best done with
//! the [`CommandTree`] in conjunction with [`Command`] and [`Parameter`].
//!
//! Start by creating a mutable [`CommandTree`] instance:
//!
//! ```
//! use commands::parser::{CommandTree, Parser};
//!
//! let mut tree = CommandTree::new();
//! ```
//!
//! Then, add your commands and arguments, and finally,
//! call `finalize` on the tree to get back a [`RootNode`]
//! that can use be used with a [`Parser`].
//!
//! ```
//! use commands::parser::{Command, CommandTree, Parameter, Parser};
//!
//! let mut tree = CommandTree::new();
//! tree.command(Command::new("again")
//!                  .hidden(false)
//!                  .parameter(Parameter::new("test")
//!                                 .required(false)
//!                                 .help("This is just a test parameter.")));
//! let root = tree.finalize();
//! let mut parser = Parser::new(root);
//! ```
//!
//! [`commands::tokenizer`]: ../tokenizer/index.html
//! [`Command`]: struct.Command.html
//! [`CommandNode`]: struct.CommandNode.html
//! [`CommandTree`]: struct.CommandTree.html
//! [`Node`]: enum.Node.html
//! [`Parameter`]: struct.Parameter.html
//! [`ParameterNode`]: trait.ParameterNode.html
//! [`Parser`]: struct.Parser.html
//! [`RootNode`]: struct.RootNode.html
//! [three kinds of parameters]: enum.ParameterKind.html

mod builder;
mod completion;
mod constants;
mod nodes;

// Re-export public API
pub use self::builder::{Command, CommandTree, Parameter};
pub use self::constants::ParameterKind;
pub use self::constants::{PRIORITY_DEFAULT, PRIORITY_MINIMUM, PRIORITY_PARAMETER};
pub use self::completion::{Completion, CompletionOption};
pub use self::nodes::{Node, NodeOps, TreeNode};
pub use self::nodes::{CommandNode, ParameterNameNode, ParameterNode, RootNode};

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::rc::Rc;
use tokenizer::{Token, TokenType};

/// Command parser
///
/// The lifetime parameter `'text` refers to the lifetime of the
/// tokens passed into the parser. This is the same as the lifetime
/// of the text used to create the tokens.
///
/// When creating a `Parser`, you must give it an `Rc<RootNode>`.
/// [`RootNode`] instances should be created using a [`CommandTree`].
///
/// ```
/// use commands::parser::{Command, CommandTree, Parser};
///
/// let mut tree = CommandTree::new();
/// tree.command(Command::new("show"));
/// tree.command(Command::new("set"));
/// tree.command(Command::new("help"));
///
/// let mut parser = Parser::new(tree.finalize());
/// ```
///
/// The parser is constructed as a `mut`able object as most of
/// the methods on it will modify its state.
///
/// [`CommandTree`]: struct.CommandTree.html
/// ['RootNode`]: struct.RootNode.html
pub struct Parser<'text> {
    current_node: Rc<Node>,
    /// The nodes which have been accepted during `parse` or `advance`.
    pub nodes: Vec<Rc<Node>>,
    /// The tokens which have been accepted during `parse` or `advance`.
    pub tokens: Vec<Token<'text>>,
    commands: Vec<Rc<Node>>,
    parameters: HashMap<String, String>,
}

impl<'text> Parser<'text> {
    /// Construct a parser with a root node.
    pub fn new(initial_node: Rc<Node>) -> Parser<'text> {
        Parser {
            current_node: initial_node,
            nodes: vec![],
            tokens: vec![],
            commands: vec![],
            parameters: HashMap::new(),
        }
    }

    /// Given an optional token, get the possible valid completions
    /// for the current parser state.
    ///
    /// Possible completions are successors of the current node which
    /// are not `hidden`, are `acceptable`, and which match the token,
    /// if one has been provided.
    ///
    /// Nodes may customize the `Complete` trait to customize the
    /// [`Completion`] and [`CompletionOption`]s which are generated
    /// for that node.
    ///
    /// Each valid successor node will have one [`Completion`] in the
    /// result vector. Each [`Completion`] will have one or more
    /// [`CompletionOption`] for each valid way that the value may be
    /// entered.
    ///
    /// ```
    /// use commands::parser::{Command, CommandTree, Parser};
    /// use commands::tokenizer::{Token, tokenize};
    ///
    /// let mut tree = CommandTree::new();
    /// tree.command(Command::new("show"));
    /// tree.command(Command::new("set"));
    /// tree.command(Command::new("help"));
    ///
    /// let mut parser = Parser::new(tree.finalize());
    ///
    /// // Completing now should have 3 options, 1 for each command.
    /// let comps = parser.complete(None);
    /// assert_eq!(comps.len(), 3);
    ///
    /// // But completing with a token for 'h' should have 1 option.
    /// if let Ok(tokens) = tokenize("h") {
    ///   let comps = parser.complete(Some(tokens[0]));
    ///   assert_eq!(comps.len(), 1);
    ///   assert_eq!(comps[0].options.len(), 1);
    ///   assert_eq!(comps[0].options[0].option_string, "help");
    /// } else {
    ///   panic!("Tokenize failed.");
    /// }
    ///
    /// // And completing for 's' should have 2 options.
    /// if let Ok(tokens) = tokenize("s") {
    ///   let comps = parser.complete(Some(tokens[0]));
    ///   assert_eq!(comps.len(), 2);
    /// } else {
    ///   panic!("Tokenize failed.");
    /// }
    /// ```
    ///
    /// [`Completion`]: struct.Completion.html
    /// [`CompletionOption`]: struct.CompletionOption.html
    pub fn complete(&self, token: Option<Token<'text>>) -> Vec<Completion> {
        self.current_node
            .successors()
            .iter()
            .filter(|n| {
                // To be a possible completion, the node should not be
                // hidden, it should be acceptable, and if there's a token,
                // it should be a valid match for the node.
                !n.node().hidden && n.acceptable(self, n) &&
                if let Some(t) = token {
                    n.matches(self, t)
                } else {
                    true
                }
            })
            .map(|n| n.complete(token))
            .collect::<Vec<_>>()
    }

    /// Parse a vector of tokens, advancing through the
    /// node hierarchy.
    ///
    /// ```
    /// use commands::parser::{Command, CommandTree, Parser};
    /// use commands::tokenizer::tokenize;
    ///
    /// let mut tree = CommandTree::new();
    /// tree.command(Command::new("show interface"));
    ///
    /// let mut parser = Parser::new(tree.finalize());
    ///
    /// if let Ok(tokens) = tokenize("show interface") {
    ///     parser.parse(tokens);
    /// }
    /// ```
    pub fn parse(&mut self, tokens: Vec<Token<'text>>) -> Result<(), ParseError<'text>> {
        for token in tokens {
            match token.token_type {
                TokenType::Whitespace => {}
                TokenType::Word => try!(self.advance(token)),
            }
        }
        Ok(())
    }

    /// Parse a single token, advancing through the node hierarchy.
    pub fn advance(&mut self, token: Token<'text>) -> Result<(), ParseError<'text>> {
        let acceptable = self.current_node
            .successors()
            .iter()
            .filter(|n| n.acceptable(self, n))
            .map(|n| n.clone())
            .collect::<Vec<_>>();
        let matches = acceptable.clone()
            .iter()
            .filter(|n| n.matches(self, token))
            .map(|n| n.clone())
            .collect::<Vec<_>>();
        match matches.len() {
            1 => {
                let matching_node = &matches[0];
                matching_node.accept(self, token, matching_node);
                self.current_node = matching_node.clone();
                self.nodes.push(matching_node.clone());
                self.tokens.push(token);
                Ok(())
            }
            0 => Err(ParseError::NoMatches(token, acceptable)),
            _ => Err(ParseError::AmbiguousMatch(token, matches)),
        }
    }

    /// Execute the command that has been accepted by the parser.
    ///
    /// * XXX: This should be returning a Result probably.
    pub fn execute(&self) {
        if !self.commands.is_empty() {
            unimplemented!();
            // self.commands[0].execute(self)
        }
    }

    /// Verify that the parser is in a valid state with
    /// respect to having accepted a command and all
    /// required parameters.
    pub fn verify(&self) -> Result<(), VerifyError> {
        if let Some(&Node::Command(ref command)) = self.commands.first().map(|n| &**n) {
            for expected in &command.parameters {
                if let Node::Parameter(ref param) = **expected {
                    let name = &param.node.name;
                    if param.required && !self.parameters.contains_key(name) {
                        return Err(VerifyError::MissingParameter(name.clone()));
                    }
                } else {
                    unreachable!();
                }
            }
            Ok(())
        } else {
            Err(VerifyError::NoCommandAccepted)
        }
    }
}

/// Errors that calling `parse` on the `Parser` can raise.
#[derive(Clone)]
pub enum ParseError<'text> {
    /// There were no matches for the token.
    NoMatches(Token<'text>, Vec<Rc<Node>>),
    /// There was more than 1 possible match for the token.
    AmbiguousMatch(Token<'text>, Vec<Rc<Node>>),
}

impl<'text> fmt::Debug for ParseError<'text> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::NoMatches(token, _) => write!(f, "NoMatches({:?}, ...)", token),
            ParseError::AmbiguousMatch(token, _) => write!(f, "AmbiguousMatch({:?}, ...)", token),
        }
    }
}

impl<'text> Error for ParseError<'text> {
    fn description(&self) -> &str {
        match *self {
            ParseError::NoMatches(_, _) => "No match.",
            ParseError::AmbiguousMatch(_, _) => "Ambiguous match.",
        }
    }
}

impl<'text> fmt::Display for ParseError<'text> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Errors that calling `verify` on the `Parser` can raise.
#[derive(Clone,Debug)]
pub enum VerifyError {
    /// No command has been accepted by the parser.
    NoCommandAccepted,
    /// A required parameter is missing.
    MissingParameter(String),
}

impl Error for VerifyError {
    fn description(&self) -> &str {
        match *self {
            VerifyError::NoCommandAccepted => "No command has been accepted by the parser.",
            VerifyError::MissingParameter(_) => "A required parameter is missing.",
        }
    }
}

impl fmt::Display for VerifyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

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

    #[test]
    #[should_panic]
    fn verify_signals_no_command() {
        let root = CommandTree::new().finalize();
        let parser = Parser::new(root);
        match parser.verify() {
            Err(VerifyError::NoCommandAccepted) => panic!(),
            _ => {}
        }
    }

    #[test]
    #[should_panic]
    fn parse_signals_no_matches() {
        let mut tree = CommandTree::new();
        tree.command(Command::new("show"));
        let mut parser = Parser::new(tree.finalize());
        if let Ok(tokens) = tokenize("h") {
            match parser.parse(tokens) {
                Err(ParseError::NoMatches(_, _)) => panic!(),
                _ => {}
            }
        }
    }

    #[test]
    #[should_panic]
    fn parse_signals_ambiguous_match() {
        let mut tree = CommandTree::new();
        tree.command(Command::new("show"));
        tree.command(Command::new("set"));
        let mut parser = Parser::new(tree.finalize());
        if let Ok(tokens) = tokenize("s") {
            match parser.parse(tokens) {
                Err(ParseError::AmbiguousMatch(_, _)) => panic!(),
                _ => {}
            }
        }
    }
}
<commit_msg>Improve Parser::advance.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Command Parser
//!
//! The command parser deals with interpreting textual input (like a
//! command line) and executing a command with the provided parameters.
//!
//! Each command has a name which is typically a series of words. Some
//! examples might be:
//!
//! * `show directory /bin`
//! * `show struct`
//! * `thread step in`
//! * `thread step out`
//! * `show process list`
//!
//! Don't worry about commands being long. Ideally, it will be rare that
//! that the entire command would be typed by applying intelligent and
//! interactive autocompletion.
//!
//! Commands can take parameters. Parameters can be marked as `required`
//! or `repeatable`. Repeatable parameters generate a list of values
//! rather than a single value.
//!
//! There are [three kinds of parameters]:
//!
//! * Simple: Just a value that is present in the command line. For
//!   example: `show interface eth0` where `eth0` is a simple
//!   parameter `name` which will have the value `eth0`.
//! * Named: A name that precedes the value in the command line. For
//!   example: `show route src <ip> dst <ip>` where `src <ip>` and
//!   `dst <ip>` are both named parameters to a command `show route`.
//! * Flag: Signify a `true` value when present. For example:
//!   `show log verbose` where `verbose` is a flag parameter that
//!   results in value of `true` when present and `false` when not.
//!
//! The command parser does not assume anything about the implementation
//! of the textual interface. It provides a mechanism for parsing tokens
//! that have been tokenized from an input and a method for communicating
//! with the embedding application for errors and autocompletion by way of
//! using structured data rather than printing to an output device (like
//! `stdout`).
//!
//! The command parser consists of two important things:
//!
//! * A tree that represents the available commands and their arguments.
//!   This tree consists of instances of implementations of [`Node`] like
//!   [`CommandNode`], [`ParameterNode`] and [`RootNode`]. Construction of this
//!   tree is done with the help of [`CommandTree`], [`Command`] and
//!   [`Parameter`].
//! * A [`Parser`] that handles input and matches it against the command
//!   tree. This parser is intended to be short-lived and to just live
//!   for the duration of parsing and evaluating a single command line
//!   input.
//!
//! ## Building A Command Tree
//!
//! The commands handled by a [`Parser`] are represented by a tree based
//! the words in the commands. For example, with commands `show directory`,
//! `show class`, `help`, and `thread step`, there are 3 leaf nodes from
//! the root and the tree is arranged like:
//!
//! * show
//!   * directory
//!   * class
//! * help
//! * thread
//!   * step
//!
//! Building a tree of nodes for use with the parser is best done with
//! the [`CommandTree`] in conjunction with [`Command`] and [`Parameter`].
//!
//! Start by creating a mutable [`CommandTree`] instance:
//!
//! ```
//! use commands::parser::{CommandTree, Parser};
//!
//! let mut tree = CommandTree::new();
//! ```
//!
//! Then, add your commands and arguments, and finally,
//! call `finalize` on the tree to get back a [`RootNode`]
//! that can use be used with a [`Parser`].
//!
//! ```
//! use commands::parser::{Command, CommandTree, Parameter, Parser};
//!
//! let mut tree = CommandTree::new();
//! tree.command(Command::new("again")
//!                  .hidden(false)
//!                  .parameter(Parameter::new("test")
//!                                 .required(false)
//!                                 .help("This is just a test parameter.")));
//! let root = tree.finalize();
//! let mut parser = Parser::new(root);
//! ```
//!
//! [`commands::tokenizer`]: ../tokenizer/index.html
//! [`Command`]: struct.Command.html
//! [`CommandNode`]: struct.CommandNode.html
//! [`CommandTree`]: struct.CommandTree.html
//! [`Node`]: enum.Node.html
//! [`Parameter`]: struct.Parameter.html
//! [`ParameterNode`]: trait.ParameterNode.html
//! [`Parser`]: struct.Parser.html
//! [`RootNode`]: struct.RootNode.html
//! [three kinds of parameters]: enum.ParameterKind.html

mod builder;
mod completion;
mod constants;
mod nodes;

// Re-export public API
pub use self::builder::{Command, CommandTree, Parameter};
pub use self::constants::ParameterKind;
pub use self::constants::{PRIORITY_DEFAULT, PRIORITY_MINIMUM, PRIORITY_PARAMETER};
pub use self::completion::{Completion, CompletionOption};
pub use self::nodes::{Node, NodeOps, TreeNode};
pub use self::nodes::{CommandNode, ParameterNameNode, ParameterNode, RootNode};

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::rc::Rc;
use tokenizer::{Token, TokenType};

/// Command parser
///
/// The lifetime parameter `'text` refers to the lifetime of the
/// tokens passed into the parser. This is the same as the lifetime
/// of the text used to create the tokens.
///
/// When creating a `Parser`, you must give it an `Rc<RootNode>`.
/// [`RootNode`] instances should be created using a [`CommandTree`].
///
/// ```
/// use commands::parser::{Command, CommandTree, Parser};
///
/// let mut tree = CommandTree::new();
/// tree.command(Command::new("show"));
/// tree.command(Command::new("set"));
/// tree.command(Command::new("help"));
///
/// let mut parser = Parser::new(tree.finalize());
/// ```
///
/// The parser is constructed as a `mut`able object as most of
/// the methods on it will modify its state.
///
/// [`CommandTree`]: struct.CommandTree.html
/// ['RootNode`]: struct.RootNode.html
pub struct Parser<'text> {
    current_node: Rc<Node>,
    /// The nodes which have been accepted during `parse` or `advance`.
    pub nodes: Vec<Rc<Node>>,
    /// The tokens which have been accepted during `parse` or `advance`.
    pub tokens: Vec<Token<'text>>,
    commands: Vec<Rc<Node>>,
    parameters: HashMap<String, String>,
}

impl<'text> Parser<'text> {
    /// Construct a parser with a root node.
    pub fn new(initial_node: Rc<Node>) -> Parser<'text> {
        Parser {
            current_node: initial_node,
            nodes: vec![],
            tokens: vec![],
            commands: vec![],
            parameters: HashMap::new(),
        }
    }

    /// Given an optional token, get the possible valid completions
    /// for the current parser state.
    ///
    /// Possible completions are successors of the current node which
    /// are not `hidden`, are `acceptable`, and which match the token,
    /// if one has been provided.
    ///
    /// Nodes may customize the `Complete` trait to customize the
    /// [`Completion`] and [`CompletionOption`]s which are generated
    /// for that node.
    ///
    /// Each valid successor node will have one [`Completion`] in the
    /// result vector. Each [`Completion`] will have one or more
    /// [`CompletionOption`] for each valid way that the value may be
    /// entered.
    ///
    /// ```
    /// use commands::parser::{Command, CommandTree, Parser};
    /// use commands::tokenizer::{Token, tokenize};
    ///
    /// let mut tree = CommandTree::new();
    /// tree.command(Command::new("show"));
    /// tree.command(Command::new("set"));
    /// tree.command(Command::new("help"));
    ///
    /// let mut parser = Parser::new(tree.finalize());
    ///
    /// // Completing now should have 3 options, 1 for each command.
    /// let comps = parser.complete(None);
    /// assert_eq!(comps.len(), 3);
    ///
    /// // But completing with a token for 'h' should have 1 option.
    /// if let Ok(tokens) = tokenize("h") {
    ///   let comps = parser.complete(Some(tokens[0]));
    ///   assert_eq!(comps.len(), 1);
    ///   assert_eq!(comps[0].options.len(), 1);
    ///   assert_eq!(comps[0].options[0].option_string, "help");
    /// } else {
    ///   panic!("Tokenize failed.");
    /// }
    ///
    /// // And completing for 's' should have 2 options.
    /// if let Ok(tokens) = tokenize("s") {
    ///   let comps = parser.complete(Some(tokens[0]));
    ///   assert_eq!(comps.len(), 2);
    /// } else {
    ///   panic!("Tokenize failed.");
    /// }
    /// ```
    ///
    /// [`Completion`]: struct.Completion.html
    /// [`CompletionOption`]: struct.CompletionOption.html
    pub fn complete(&self, token: Option<Token<'text>>) -> Vec<Completion> {
        self.current_node
            .successors()
            .iter()
            .filter(|n| {
                // To be a possible completion, the node should not be
                // hidden, it should be acceptable, and if there's a token,
                // it should be a valid match for the node.
                !n.node().hidden && n.acceptable(self, n) &&
                if let Some(t) = token {
                    n.matches(self, t)
                } else {
                    true
                }
            })
            .map(|n| n.complete(token))
            .collect::<Vec<_>>()
    }

    /// Parse a vector of tokens, advancing through the
    /// node hierarchy.
    ///
    /// ```
    /// use commands::parser::{Command, CommandTree, Parser};
    /// use commands::tokenizer::tokenize;
    ///
    /// let mut tree = CommandTree::new();
    /// tree.command(Command::new("show interface"));
    ///
    /// let mut parser = Parser::new(tree.finalize());
    ///
    /// if let Ok(tokens) = tokenize("show interface") {
    ///     parser.parse(tokens);
    /// }
    /// ```
    pub fn parse(&mut self, tokens: Vec<Token<'text>>) -> Result<(), ParseError<'text>> {
        for token in tokens {
            match token.token_type {
                TokenType::Whitespace => {}
                TokenType::Word => try!(self.advance(token)),
            }
        }
        Ok(())
    }

    /// Parse a single token, advancing through the node hierarchy.
    pub fn advance(&mut self, token: Token<'text>) -> Result<(), ParseError<'text>> {
        let matches = self.current_node
            .successors()
            .iter()
            .filter(|n| n.acceptable(self, n) && n.matches(self, token))
            .cloned()
            .collect::<Vec<_>>();
        match matches.len() {
            1 => {
                let matching_node = &matches[0];
                matching_node.accept(self, token, matching_node);
                self.current_node = matching_node.clone();
                self.nodes.push(matching_node.clone());
                self.tokens.push(token);
                Ok(())
            }
            0 => {
                Err(ParseError::NoMatches(token,
                                          self.current_node
                                              .successors()
                                              .iter()
                                              .filter(|n| n.acceptable(self, n))
                                              .cloned()
                                              .collect::<Vec<_>>()))
            }
            _ => Err(ParseError::AmbiguousMatch(token, matches)),
        }
    }

    /// Execute the command that has been accepted by the parser.
    ///
    /// * XXX: This should be returning a Result probably.
    pub fn execute(&self) {
        if !self.commands.is_empty() {
            unimplemented!();
            // self.commands[0].execute(self)
        }
    }

    /// Verify that the parser is in a valid state with
    /// respect to having accepted a command and all
    /// required parameters.
    pub fn verify(&self) -> Result<(), VerifyError> {
        if let Some(&Node::Command(ref command)) = self.commands.first().map(|n| &**n) {
            for expected in &command.parameters {
                if let Node::Parameter(ref param) = **expected {
                    let name = &param.node.name;
                    if param.required && !self.parameters.contains_key(name) {
                        return Err(VerifyError::MissingParameter(name.clone()));
                    }
                } else {
                    unreachable!();
                }
            }
            Ok(())
        } else {
            Err(VerifyError::NoCommandAccepted)
        }
    }
}

/// Errors that calling `parse` on the `Parser` can raise.
#[derive(Clone)]
pub enum ParseError<'text> {
    /// There were no matches for the token.
    NoMatches(Token<'text>, Vec<Rc<Node>>),
    /// There was more than 1 possible match for the token.
    AmbiguousMatch(Token<'text>, Vec<Rc<Node>>),
}

impl<'text> fmt::Debug for ParseError<'text> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::NoMatches(token, _) => write!(f, "NoMatches({:?}, ...)", token),
            ParseError::AmbiguousMatch(token, _) => write!(f, "AmbiguousMatch({:?}, ...)", token),
        }
    }
}

impl<'text> Error for ParseError<'text> {
    fn description(&self) -> &str {
        match *self {
            ParseError::NoMatches(_, _) => "No match.",
            ParseError::AmbiguousMatch(_, _) => "Ambiguous match.",
        }
    }
}

impl<'text> fmt::Display for ParseError<'text> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Errors that calling `verify` on the `Parser` can raise.
#[derive(Clone,Debug)]
pub enum VerifyError {
    /// No command has been accepted by the parser.
    NoCommandAccepted,
    /// A required parameter is missing.
    MissingParameter(String),
}

impl Error for VerifyError {
    fn description(&self) -> &str {
        match *self {
            VerifyError::NoCommandAccepted => "No command has been accepted by the parser.",
            VerifyError::MissingParameter(_) => "A required parameter is missing.",
        }
    }
}

impl fmt::Display for VerifyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

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

    #[test]
    #[should_panic]
    fn verify_signals_no_command() {
        let root = CommandTree::new().finalize();
        let parser = Parser::new(root);
        match parser.verify() {
            Err(VerifyError::NoCommandAccepted) => panic!(),
            _ => {}
        }
    }

    #[test]
    #[should_panic]
    fn parse_signals_no_matches() {
        let mut tree = CommandTree::new();
        tree.command(Command::new("show"));
        let mut parser = Parser::new(tree.finalize());
        if let Ok(tokens) = tokenize("h") {
            match parser.parse(tokens) {
                Err(ParseError::NoMatches(_, _)) => panic!(),
                _ => {}
            }
        }
    }

    #[test]
    #[should_panic]
    fn parse_signals_ambiguous_match() {
        let mut tree = CommandTree::new();
        tree.command(Command::new("show"));
        tree.command(Command::new("set"));
        let mut parser = Parser::new(tree.finalize());
        if let Ok(tokens) = tokenize("s") {
            match parser.parse(tokens) {
                Err(ParseError::AmbiguousMatch(_, _)) => panic!(),
                _ => {}
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::fitness::Fitness;
use super::traits::{Genotype, Distance};
use super::selection;
use rand::{Rng, Closed01};
use super::traits::Mate;
use std::marker::PhantomData;
use std::num::Zero;
use std::fmt::Debug;
use std::cmp;
use rayon::par_iter::*;
use super::prob::probabilistic_round;

#[derive(Debug)]
pub struct Individual<T: Debug + Genotype> {
    fitness: Fitness,
    genome: Box<T>,
}

impl<T: Debug + Genotype> Individual<T> {
    pub fn fitness(&self) -> Fitness {
        self.fitness
    }

    pub fn genome(&self) -> &T {
        &self.genome
    }
}

pub trait Rating {}

#[derive(Debug)]
pub struct Unrated;

#[derive(Debug)]
pub struct Rated;

impl Rating for Unrated {}
impl Rating for Rated {}

#[derive(Debug)]
pub struct Population<T: Genotype + Debug, R: Rating> {
    individuals: Vec<Individual<T>>,
    _marker: PhantomData<R>,
}

impl<T: Genotype + Debug, R: Rating> Population<T, R> {
    pub fn new() -> Population<T, R> {
        Population {
            individuals: Vec::new(),
            _marker: PhantomData,
        }
    }

    pub fn new_from_vec(v: Vec<Individual<T>>) -> Population<T, R> {
        Population {
            individuals: v,
            _marker: PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }
}

impl<T: Genotype + Debug> Population<T, Unrated> {
    pub fn add_genome(&mut self, genome: Box<T>) {
        self.individuals.push(Individual {
            fitness: Zero::zero(),
            genome: genome,
        });
    }

    pub fn rate<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Fn(&T) -> Fitness
    {
        for ind in self.individuals.iter_mut() {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        }
        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }

    pub fn rate_par<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Sync + Fn(&T) -> Fitness
    {
        self.individuals.par_iter_mut().for_each(|ind| {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        });

        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }
}

impl<T: Genotype + Debug> Population<T, Rated> {
    pub fn add_individual(&mut self, ind: Individual<T>) {
        self.individuals.push(ind);
    }

    // Return true if genome at position `i` is fitter that `j`
    // XXX: If population is sorted, we only have to check the indices!
    fn is_fitter(&self, i: usize, j: usize) -> bool {
        self.individuals[i].fitness > self.individuals[j].fitness
    }

    fn mean_fitness(&self) -> Fitness {
        let sum: Fitness = self.individuals.iter().map(|ind| ind.fitness).sum();
        sum / Fitness::new(self.len() as f64)
    }

    pub fn max_fitness(&self) -> Option<Fitness> {
        self.individuals.iter().max_by_key(|ind| ind.fitness).map(|i| i.fitness)
    }

    pub fn best_individual(&self) -> Option<&Individual<T>> {
        self.individuals.iter().max_by_key(|ind| ind.fitness)
    }

    // higher value of fitness means that the individual is fitter.
    pub fn sort(mut self) -> Self {
        (&mut self.individuals).sort_by(|a, b| a.fitness.cmp(&b.fitness).reverse());
        self
    }

    /// Merge `self` with the first `n` individuals from population `other`.
    pub fn merge(&mut self, other: Population<T, Rated>, n: Option<usize>) {
        let len = other.individuals.len();
        self.individuals.extend(other.individuals.into_iter().take(n.unwrap_or(len)));
    }

    // We want to create a population of approximately `pop_size`. We do not care if there are
    // slightly more or slightly less individuals than that.
    //
    // 1. sort whole popluation into niches
    // 2. calculate the number of offspring for each niche.
    // 3. each niche produces offspring.
    //    - sort each niche according to the fitness value.
    //    - r% of the best genomes produce offspring
    //    - determine the elitist size. those are always copied into the new generation.
    //
    pub fn produce_offspring<C, M, R>(self,
                                      pop_size: usize,
                                      // how many of the best individuals of a niche are copied as-is into the
                                      // new population?
                                      elite_percentage: Closed01<f64>,
                                      // how many of the best individuals of a niche are selected for
                                      // reproduction?
                                      selection_percentage: Closed01<f64>,
                                      tournament_k: usize,
                                      compatibility_threshold: f64,
                                      compatibility: &C,
                                      mate: &mut M,
                                      rng: &mut R)
                                      -> (Population<T, Rated>, Population<T, Unrated>)
        where R: Rng,
              C: Distance<T>,
              M: Mate<T>
    {
        debug!("population size: {}", self.len());

        assert!(elite_percentage.0 <= selection_percentage.0); // XXX
        assert!(self.len() > 0);
        let niches = self.partition(rng, compatibility_threshold, compatibility);
        let num_niches = niches.len();

        debug!("number of niches: {}", num_niches);

        assert!(num_niches > 0);
        let total_mean: Fitness = niches.iter().map(|ind| ind.mean_fitness()).sum();
        assert!(total_mean.get() >= 0.0);

        let mut new_unrated_population: Population<T, Unrated> = Population::new();
        let mut new_rated_population: Population<T, Rated> = Population::new();

        for niche in niches.into_iter() {
            let percentage_of_population: f64 = if total_mean.get() == 0.0 {
                // all individuals have a fitness of 0.0.
                // we will equally allow each niche to procude offspring.
                1.0 / (num_niches as f64)
            } else {
                (niche.mean_fitness() / total_mean).get()
            };

            // calculate new size of niche, and size of elites, and selection size.
            assert!(percentage_of_population >= 0.0 && percentage_of_population <= 1.0);

            let niche_size = pop_size as f64 * percentage_of_population;

            // number of elitary individuals to copy from the old niche generation into the new.
            let elite_size =
                cmp::max(1,
                         probabilistic_round(niche_size * elite_percentage.0, rng) as usize);

            // number of offspring to produce.
            let offspring_size = probabilistic_round(niche_size * (1.0 - elite_percentage.0),
                                                     rng) as usize;

            // number of the best individuals to use for mating.
            let select_size = probabilistic_round(niche_size *
                                                  selection_percentage.0,
                                                  rng) as usize;

            let sorted_niche = niche.sort();

            let select_size = cmp::min(select_size, sorted_niche.len());

            // at first produce `offspring_size` individuals from the top `select_size`
            // individuals.
            if select_size > 0 {
                let mut n = offspring_size;
                while n > 0 {
                    let (parent1, parent2) =
                        selection::tournament_selection_fast2(rng,
                                                              // XXX: in a sorted niche, the
                                                              // individuals with the lower index
                                                              // has better fitness.
                                                              &|i, j| sorted_niche.is_fitter(i, j),
                                                              select_size,
                                                              cmp::min(select_size, tournament_k),
                                                              3);

                    // `mate` assumes that the left parent performs better.
                    // XXX: `is_fitter` same as above.
                    let (left, right) = if sorted_niche.is_fitter(parent1, parent2) {
                        (parent1, parent2)
                    } else {
                        (parent2, parent1)
                    };
                    let offspring = mate.mate(&sorted_niche.individuals[left].genome,
                                              &sorted_niche.individuals[right].genome,
                                              left == right,
                                              rng);
                    new_unrated_population.add_genome(Box::new(offspring));
                    n -= 1;
                }
            }

            // now copy the elites
            new_rated_population.merge(sorted_niche, Some(elite_size));
        }

        return (new_rated_population, new_unrated_population);
    }

    // Partitions the whole population into species (niches)
    fn partition<R, C>(self,
                       rng: &mut R,
                       compatibility_threshold: f64,
                       compatibility: &C)
                       -> Vec<Population<T, Rated>>
        where R: Rng,
              C: Distance<T>
    {
        let mut niches: Vec<Population<T, Rated>> = Vec::new();

        'outer: for ind in self.individuals.into_iter() {
            for niche in niches.iter_mut() {
                // Is this genome compatible with this niche? Test against a random genome.
                let compatible = match rng.choose(&niche.individuals) {
                    Some(probe) => {
                        compatibility.distance(&probe.genome, &ind.genome) < compatibility_threshold
                    }
                    // If a niche is empty, a genome always is compatible (note that a niche can't be empyt)
                    None => true,
                };
                if compatible {
                    niche.add_individual(ind);
                    continue 'outer;
                }
            }
            // if no compatible niche was found, create a new niche containing this genome.
            let mut new_niche = Population::new();
            new_niche.add_individual(ind);
            niches.push(new_niche);
        }

        niches
    }
}

pub struct Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    // anticipated population size
    pub pop_size: usize,
    // how many of the best individuals of a niche are copied as-is into the
    // new population?
    pub elite_percentage: Closed01<f64>,
    // how many of the best individuals of a niche are selected for
    // reproduction?
    pub selection_percentage: Closed01<f64>,
    pub tournament_k: usize,
    pub compatibility_threshold: f64,
    pub compatibility: &'a C,
    pub mate: &'a mut M,
    pub fitness: &'a F,
    pub _marker: PhantomData<T>,
}

impl<'a, T, C, M, F> Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    pub fn run<R, G>(&mut self,
                     initial_pop: Population<T, Unrated>,
                     goal_condition: &G,
                     rng: &mut R)
                     -> (usize, Population<T, Rated>)
        where R: Rng,
              G: Fn(usize, &Population<T, Rated>) -> bool
    {
        let mut iteration: usize = 0;
        let mut current_rated_pop = initial_pop.rate_par(self.fitness);

        while !goal_condition(iteration, &current_rated_pop) {
            let (new_rated, new_unrated) =
                current_rated_pop.produce_offspring(self.pop_size,
                                                    Closed01(self.elite_percentage.0),
                                                    Closed01(self.selection_percentage.0),
                                                    self.tournament_k,
                                                    self.compatibility_threshold,
                                                    self.compatibility,
                                                    self.mate,
                                                    rng);

            current_rated_pop = new_rated;
            current_rated_pop.merge(new_unrated.rate_par(self.fitness), None);
            iteration += 1;
        }

        return (iteration, current_rated_pop);
    }
}
<commit_msg>In a sorted niche, individuals with lower index have a better fitness.<commit_after>use super::fitness::Fitness;
use super::traits::{Genotype, Distance};
use super::selection;
use rand::{Rng, Closed01};
use super::traits::Mate;
use std::marker::PhantomData;
use std::num::Zero;
use std::fmt::Debug;
use std::cmp;
use rayon::par_iter::*;
use super::prob::probabilistic_round;

#[derive(Debug)]
pub struct Individual<T: Debug + Genotype> {
    fitness: Fitness,
    genome: Box<T>,
}

impl<T: Debug + Genotype> Individual<T> {
    pub fn fitness(&self) -> Fitness {
        self.fitness
    }

    pub fn genome(&self) -> &T {
        &self.genome
    }
}

pub trait Rating {}

#[derive(Debug)]
pub struct Unrated;

#[derive(Debug)]
pub struct Rated;

impl Rating for Unrated {}
impl Rating for Rated {}

#[derive(Debug)]
pub struct Population<T: Genotype + Debug, R: Rating> {
    individuals: Vec<Individual<T>>,
    _marker: PhantomData<R>,
}

impl<T: Genotype + Debug, R: Rating> Population<T, R> {
    pub fn new() -> Population<T, R> {
        Population {
            individuals: Vec::new(),
            _marker: PhantomData,
        }
    }

    pub fn new_from_vec(v: Vec<Individual<T>>) -> Population<T, R> {
        Population {
            individuals: v,
            _marker: PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }
}

impl<T: Genotype + Debug> Population<T, Unrated> {
    pub fn add_genome(&mut self, genome: Box<T>) {
        self.individuals.push(Individual {
            fitness: Zero::zero(),
            genome: genome,
        });
    }

    pub fn rate<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Fn(&T) -> Fitness
    {
        for ind in self.individuals.iter_mut() {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        }
        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }

    pub fn rate_par<F>(mut self, f: &F) -> Population<T, Rated>
        where F: Sync + Fn(&T) -> Fitness
    {
        self.individuals.par_iter_mut().for_each(|ind| {
            let fitness = f(&ind.genome);
            ind.fitness = fitness;
        });

        Population {
            individuals: self.individuals,
            _marker: PhantomData,
        }
    }
}

impl<T: Genotype + Debug> Population<T, Rated> {
    pub fn add_individual(&mut self, ind: Individual<T>) {
        self.individuals.push(ind);
    }

    // Return true if genome at position `i` is fitter that `j`
    // XXX: If population is sorted, we only have to check the indices!
    //fn is_fitter(&self, i: usize, j: usize) -> bool {
    //    self.individuals[i].fitness > self.individuals[j].fitness
    //}

    fn mean_fitness(&self) -> Fitness {
        let sum: Fitness = self.individuals.iter().map(|ind| ind.fitness).sum();
        sum / Fitness::new(self.len() as f64)
    }

    pub fn max_fitness(&self) -> Option<Fitness> {
        self.individuals.iter().max_by_key(|ind| ind.fitness).map(|i| i.fitness)
    }

    pub fn best_individual(&self) -> Option<&Individual<T>> {
        self.individuals.iter().max_by_key(|ind| ind.fitness)
    }

    // higher value of fitness means that the individual is fitter.
    pub fn sort(mut self) -> Self {
        (&mut self.individuals).sort_by(|a, b| a.fitness.cmp(&b.fitness).reverse());
        self
    }

    /// Merge `self` with the first `n` individuals from population `other`.
    pub fn merge(&mut self, other: Population<T, Rated>, n: Option<usize>) {
        let len = other.individuals.len();
        self.individuals.extend(other.individuals.into_iter().take(n.unwrap_or(len)));
    }

    // We want to create a population of approximately `pop_size`. We do not care if there are
    // slightly more or slightly less individuals than that.
    //
    // 1. sort whole popluation into niches
    // 2. calculate the number of offspring for each niche.
    // 3. each niche produces offspring.
    //    - sort each niche according to the fitness value.
    //    - r% of the best genomes produce offspring
    //    - determine the elitist size. those are always copied into the new generation.
    //
    pub fn produce_offspring<C, M, R>(self,
                                      pop_size: usize,
                                      // how many of the best individuals of a niche are copied as-is into the
                                      // new population?
                                      elite_percentage: Closed01<f64>,
                                      // how many of the best individuals of a niche are selected for
                                      // reproduction?
                                      selection_percentage: Closed01<f64>,
                                      tournament_k: usize,
                                      compatibility_threshold: f64,
                                      compatibility: &C,
                                      mate: &mut M,
                                      rng: &mut R)
                                      -> (Population<T, Rated>, Population<T, Unrated>)
        where R: Rng,
              C: Distance<T>,
              M: Mate<T>
    {
        debug!("population size: {}", self.len());

        assert!(elite_percentage.0 <= selection_percentage.0); // XXX
        assert!(self.len() > 0);
        let niches = self.partition(rng, compatibility_threshold, compatibility);
        let num_niches = niches.len();

        debug!("number of niches: {}", num_niches);

        assert!(num_niches > 0);
        let total_mean: Fitness = niches.iter().map(|ind| ind.mean_fitness()).sum();
        assert!(total_mean.get() >= 0.0);

        let mut new_unrated_population: Population<T, Unrated> = Population::new();
        let mut new_rated_population: Population<T, Rated> = Population::new();

        for niche in niches.into_iter() {
            let percentage_of_population: f64 = if total_mean.get() == 0.0 {
                // all individuals have a fitness of 0.0.
                // we will equally allow each niche to procude offspring.
                1.0 / (num_niches as f64)
            } else {
                (niche.mean_fitness() / total_mean).get()
            };

            // calculate new size of niche, and size of elites, and selection size.
            assert!(percentage_of_population >= 0.0 && percentage_of_population <= 1.0);

            let niche_size = pop_size as f64 * percentage_of_population;

            // number of elitary individuals to copy from the old niche generation into the new.
            let elite_size =
                cmp::max(1,
                         probabilistic_round(niche_size * elite_percentage.0, rng) as usize);

            // number of offspring to produce.
            let offspring_size = probabilistic_round(niche_size * (1.0 - elite_percentage.0),
                                                     rng) as usize;

            // number of the best individuals to use for mating.
            let select_size = probabilistic_round(niche_size *
                                                  selection_percentage.0,
                                                  rng) as usize;

            let sorted_niche = niche.sort();

            let select_size = cmp::min(select_size, sorted_niche.len());

            // at first produce `offspring_size` individuals from the top `select_size`
            // individuals.
            if select_size > 0 {
                let mut n = offspring_size;
                while n > 0 {
                    let (parent1, parent2) =
                        selection::tournament_selection_fast2(rng,
                                                              // in a sorted niche, the individual with the lower index
                                                              // has a better fitness.
                                                              &|i, j| i < j,
                                                              select_size,
                                                              cmp::min(select_size, tournament_k),
                                                              3);

                    // `mate` assumes that the left parent performs better.
                    // In a sorted niche, the individual with lower index has better fitness.
                    let (left, right) = if parent1 < parent2 {
                        (parent1, parent2)
                    } else {
                        (parent2, parent1)
                    };
                    let offspring = mate.mate(&sorted_niche.individuals[left].genome,
                                              &sorted_niche.individuals[right].genome,
                                              left == right,
                                              rng);
                    new_unrated_population.add_genome(Box::new(offspring));
                    n -= 1;
                }
            }

            // now copy the elites
            new_rated_population.merge(sorted_niche, Some(elite_size));
        }

        return (new_rated_population, new_unrated_population);
    }

    // Partitions the whole population into species (niches)
    fn partition<R, C>(self,
                       rng: &mut R,
                       compatibility_threshold: f64,
                       compatibility: &C)
                       -> Vec<Population<T, Rated>>
        where R: Rng,
              C: Distance<T>
    {
        let mut niches: Vec<Population<T, Rated>> = Vec::new();

        'outer: for ind in self.individuals.into_iter() {
            for niche in niches.iter_mut() {
                // Is this genome compatible with this niche? Test against a random genome.
                let compatible = match rng.choose(&niche.individuals) {
                    Some(probe) => {
                        compatibility.distance(&probe.genome, &ind.genome) < compatibility_threshold
                    }
                    // If a niche is empty, a genome always is compatible (note that a niche can't be empyt)
                    None => true,
                };
                if compatible {
                    niche.add_individual(ind);
                    continue 'outer;
                }
            }
            // if no compatible niche was found, create a new niche containing this genome.
            let mut new_niche = Population::new();
            new_niche.add_individual(ind);
            niches.push(new_niche);
        }

        niches
    }
}

pub struct Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    // anticipated population size
    pub pop_size: usize,
    // how many of the best individuals of a niche are copied as-is into the
    // new population?
    pub elite_percentage: Closed01<f64>,
    // how many of the best individuals of a niche are selected for
    // reproduction?
    pub selection_percentage: Closed01<f64>,
    pub tournament_k: usize,
    pub compatibility_threshold: f64,
    pub compatibility: &'a C,
    pub mate: &'a mut M,
    pub fitness: &'a F,
    pub _marker: PhantomData<T>,
}

impl<'a, T, C, M, F> Runner<'a, T, C, M, F>
    where T: Genotype + Debug,
          C: Distance<T> + 'a,
          M: Mate<T> + 'a,
          F: Sync + Fn(&T) -> Fitness + 'a
{
    pub fn run<R, G>(&mut self,
                     initial_pop: Population<T, Unrated>,
                     goal_condition: &G,
                     rng: &mut R)
                     -> (usize, Population<T, Rated>)
        where R: Rng,
              G: Fn(usize, &Population<T, Rated>) -> bool
    {
        let mut iteration: usize = 0;
        let mut current_rated_pop = initial_pop.rate_par(self.fitness);

        while !goal_condition(iteration, &current_rated_pop) {
            let (new_rated, new_unrated) =
                current_rated_pop.produce_offspring(self.pop_size,
                                                    Closed01(self.elite_percentage.0),
                                                    Closed01(self.selection_percentage.0),
                                                    self.tournament_k,
                                                    self.compatibility_threshold,
                                                    self.compatibility,
                                                    self.mate,
                                                    rng);

            current_rated_pop = new_rated;
            current_rated_pop.merge(new_unrated.rate_par(self.fitness), None);
            iteration += 1;
        }

        return (iteration, current_rated_pop);
    }
}
<|endoftext|>


<commit_before><commit_msg>largest-series-product: Add stub<commit_after>#[derive(Debug, PartialEq)]
pub enum Error {
    SpanTooLong,
    InvalidDigit(char),
}

pub fn lsp(string_digits: &str, span: usize) -> Result<u64, Error> {
    unimplemented!("largest series product of a span of {} digits in {}", span, string_digits);
}
<|endoftext|>